extended attributes, spotlight and xcode screenshots

If you shall find yourself wondering, as i did, how exactly does Xcode know which device too what screenshot from the ones it manages the answer is simple, it just saves extended attributes for the files with the device id under com.apple.DTDeviceKit.screenshot.device_id e.g.

[valexa@VAiMac:~] $ xattr -l /Volumes/Storage/Screenshots/Screenshot 2010.07.13 01.43.57.png
com.apple.DTDeviceKit.screenshot.device_id: 5a14571ebe34512345b7345e13454a

Finder being finder has no way whatsoever to display or search for extended attributes, however some useful spotlight metadata is saved (the spotlight metadata itself used to be saved as extended com.apple.metadata attributes and xattr is still the only way to edit it) :

[valexa@VAiMac:~] $ mdls /Volumes/Storage/Screenshots/Screenshot 2010.07.13 01.43.57.png
….
kMDItemPixelHeight = 1024
kMDItemPixelWidth = 768
….

This can in fact be searched with finder even if not readily apparent, you have to add a specific Raw Query for it to understand the raw commands that you would have given to mdfind e.g.:

[valexa@VAiMac:~] $ mdfind -onlyin /Volumes/Backup kMDItemIsScreenCapture == 1
/Volumes/Backup/10.8/Screen Shot 2012-03-03 at 12.00.30 AM.png

This searches for screenshots taken from your mac (you can search for specific types for example whole screen ones with kMDItemScreenCaptureType == “display”, screenshots taken of specific windows with kMDItemScreenCaptureType == “window” or “selection” etc)

I had to do this because my screenshots folder contains both the Xcode ones and my mac screenshots, my specific goal was to figure out why some iOS screenshots there no longer showed under their corresponding devices, it turns out that i edited some with Photoshop and it replaced the extended attributes.

Editing those attributes with finder and AppleScript while possible is extremely convulted and employs shell calls anyway so we just head back to Terminal with the newfound knowledge of what screenshots we have.

Now if you only have one device for each screen resolutions available in iOS you are in luck, to print the extended attributes for iPhone, iPhone Retina, iPad, iPad Retina respectively, you can do:

mdfind -onlyin /Volumes/Storage/Screenshots/ “kMDItemPixelWidth == 480 || kMDItemPixelHeight == 480” -0 | xargs -0 xattr -l
mdfind -onlyin /Volumes/Storage/Screenshots/ “kMDItemPixelWidth == 960 || kMDItemPixelHeight == 960” -0 | xargs -0 xattr -l
mdfind -onlyin /Volumes/Storage/Screenshots/ “kMDItemPixelWidth == 768 || kMDItemPixelHeight == 768” -0 | xargs -0 xattr -l
mdfind -onlyin /Volumes/Storage/Screenshots/ “kMDItemPixelWidth == 1536 || kMDItemPixelHeight == 1536” -0 | xargs -0 xattr -l

Now that you seen your device id’s of the screenshots with proper attributes you can go ahead an set the proper id for all screenshots for a screen type e.g.:

mdfind -onlyin /Volumes/Storage/Screenshots/ “kMDItemPixelWidth == 480 || kMDItemPixelHeight == 480” -0 | xargs -0 xattr -w com.apple.DTDeviceKit.screenshot.device_id ‘5a14571ebe34512345b7345e13454a’

Xcode will immediately catch on the change and credit the screenshot properly for it’s source device.

Advertisements

enforcing iAd implementations


There seems to be a significant issue with the iAd implementation at the moment, the ads themselves are not cached on the operating system, and that has two major implications:
1 – ads can be disabled by the user by just turning off the network connection
2 – the user has incentive to disable ads under pricy data plans as every load adds to their data quota

To a developer this gives a strong incentive to both give the user the ability to purchase a removal of ads and make sure the user does not turn adds off otherwise (i am even starting to see places advising users to do so) i will go on showing how to do both and all the code is given as a xcode project attached.

Wether you have a free application and your business model depends solely on iAd’s or you monetize in other ways, if you implemented iAd you have to acknowledge the next thing:
People will want to remove the ads if at all possible, if you implemented iAd you should also allow the user to make an in app purchase for removing the ads, i will also show you how to do that in the code attached as a xcode project.


Do not get me wrong, i believe that some of the users will make the right choice and pay compensation in return of removing the ads if you give them that option, but a lot of the people will make the choice of depriving you of your ad income if they can make them stop loading.
So i will also show you how to implement a way to check if a ad was loaded after a amount of time and effectively disable the application otherwise, you can find the code in the xcode project attached.

I want to end with saying that this is clearly not a ideal situation and i hope that Apple will move quickly to address both issues 1 and 2 from within the operating system which would make a lot of sense and is a case of how they should have leveraged the fact that they built it within the operating system in the first place.

Now i will give you some details about the code, it supports all interface orientations, all devices, it requires 2 frameworks (iAd and StoreKit with iAd being weak linked) , the bulk of the code is in iAdAppViewController, this is the only one you need to edit to suit your interface and change com.foo.bar.removeads to your ProductID, besides that there is a PaymentObserver class that handles the in-app purchasing.

AdAppViewController must implement the PaymentObserverDelegate and ADBannerViewDelegate protocols, it subclasses viewDidLoad to do the initializations, viewDidAppear to position the elements, adLoadCheck to check if the ad was loaded, adsButtonPressed for when the user buys, removedAdsPurchased for when the purchase is confirmed, bannerViewDidLoadAd fires when an ad loads and willAnimateRotationToInterfaceOrientation when the device orientation is changed, resizeBanner is the code called to position/reposition the ad and the other elements in your interface.

ADBannerView *adBanner is the banner itself,  UIButton *adButton is the button above the ad to purchase ad removal, UIView *adBlockView is the view presented over the interface as shown in the image to the right.

I will not go into more detail than this other than to say it was all tested and should work as expected, but i did not implement this myself and i give no absolute guarantees , if you have any specific question leave it as a comment.