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

iOS and vectorial artwork

Any conscious iOS developer wants his artwork to look as good as possible, and with the retina display for example we were told to upgrade our artwork to higher resolution, which involved alternative @2x versions for each file and gets daunting fast if you have a lot of artwork files, and especially if a lot of your artwork is vectorial and you could just use it directly.

A popular vectorial format is PDF, and Apple has implemented a lot of the resolution independent artwork in their OSX apps as PDF, unfortunately there is no straightforward way to do that, the iOS SDK does not yet have the PDFKit.framework that exists on OSX (Interface Builder does still accept pdf files as images but they will not show on iOS) so what is there to do ?

Well the only way to do it currently is to set your artwork images in code, after rendering the PDF file into a UIImage, there are a couple of approaches to this and i am going to show you the one i use :

#include <dlfcn.h>

-(UIImage *)UIImageFromPDF:(NSString*)fileName size:(CGSize)size{
    CFURLRef pdfURL = CFBundleCopyResourceURL(CFBundleGetMainBundle(), (CFStringRef)fileName, NULL, NULL);
    if (pdfURL) {
        CGPDFDocumentRef pdf = CGPDFDocumentCreateWithURL(pdfURL);
        CFRelease(pdfURL);
        //create context with scaling 0.0 as to get the main screen's if iOS4+
        if (dlsym(RTLD_DEFAULT,"UIGraphicsBeginImageContextWithOptions") == NULL) {
            UIGraphicsBeginImageContext(size);
        }else {
            UIGraphicsBeginImageContextWithOptions(size,NO,0.0);
        }
        CGContextRef context = UIGraphicsGetCurrentContext();
        //translate the content
        CGContextTranslateCTM(context, 0.0, size.height);
        CGContextScaleCTM(context, 1.0, -1.0);
        CGContextSaveGState(context);
        //scale to our desired size
        CGPDFPageRef page = CGPDFDocumentGetPage(pdf, 1);
        CGAffineTransform pdfTransform = CGPDFPageGetDrawingTransform(page,kCGPDFCropBox,CGRectMake(0,0,size.width,size.height),0,true);
        CGContextConcatCTM(context, pdfTransform);
        CGContextDrawPDFPage(context, page);
        CGContextRestoreGState(context);
        //return autoreleased UIImage
        UIImage *ret = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        CGPDFDocumentRelease(pdf);
        return ret;
    }else {
        NSLog(@"Could not load %@",fileName);
    }
    return nil;
}

Typically you would use it like this : [someButton setImage:[self UIImageFromPDF:@”search.pdf” size:CGSizeMake(20,20)] forState:UIControlStateNormal];

The best thing about this is that it not only makes your artwork compatible with the current form and scaling factors, but most likely with further ones as well.

This is compatible with iOS 3.0+ and has been tested on iPhone and iPad, it is compatible with any resolution scaling (retina display has 2.0 for example) , i have also attached 4 pdf icons to get you started (created with Photoshop, exported with no layers or color profiles).

If for some reason you do not want to #include dlfcn.h and use dlsym() you can weak link UIKit and just check if UIGraphicsBeginImageContextWithOptions is NULL, or obviously if you are not supporting anything before iOS4 remove the conditional altogether.

NOTE: technically on IOS 4  you can currently exploit a bug and load a pdf file from [UIImage imageNamed:@”filename”] by stripping the extension, however the default size of the artwork in the pdf has to be exactly the size of the UIImage you want, if it gets scaled significant pixelation occurs basically making this shortcut unfeasible, plus it could stop working altogether at any time.

Safari-like Reader for any browser including Mobile Safari

We all like the new feature in Safari 5, Reader, well maybe except the advertisers, it is so pristine as anything we would expect from Apple but as it turns out it is actually based on the work of NYC based design house arc90, namely Readability which is acknowledged by Apple in file:///Applications/Safari.app/Contents/Resources/Acknowledgments.html

If you visit their Readability page you will notice that it is implemented as a javascript bookmarklet useable in any browser (i tested Chrome and Firefox) , all you have to do is drag the link to the bookmarks bar, for Mobile Safari which does not have such a bar it is a bit more complicated:
1 – create a placeholder bookmark by pressing plus (can be any page), press Save
2 – copy the javascript at the bottom of this post into the pasteboard
3 – press bookmarks > press edit > press the arrow on the shortcut you created
4 – press the round x to clear the name and type say Readability
5 – select the bottom field, press the round x to clear the address and paste the text

javascript:(function(){readStyle='style-newspaper';readSize='size-medium';readMargin='margin-wide';_readability_script=document.createElement('SCRIPT');_readability_script.type='text/javascript';_readability_script.src='http://lab.arc90.com/experiments/readability/js/readability.js?x='+(Math.random());document.getElementsByTagName('head')[0].appendChild(_readability_script);_readability_css=document.createElement('LINK');_readability_css.rel='stylesheet';_readability_css.href='http://lab.arc90.com/experiments/readability/css/readability.css';_readability_css.type='text/css';_readability_css.media='all';document.getElementsByTagName('head')[0].appendChild(_readability_css);_readability_print_css=document.createElement('LINK');_readability_print_css.rel='stylesheet';_readability_print_css.href='http://lab.arc90.com/experiments/readability/css/readability-print.css';_readability_print_css.media='print';_readability_print_css.type='text/css';document.getElementsByTagName('head')[0].appendChild(_readability_print_css);})();

Now when you want to see only the content on a page you are visiting just tap the newly created bookmark and you are all set.
Just in case you want to enhance your Mobile Safari even more you might want to check out http://ipuhelin.com/en/safariplus/ ,in page text search is a must-have if you ask me.

adapting web interfaces to the iPad

I decided to write this on the heels on the impending iPad launch, but is is just as valid for the iPhone as well, maybe just a bit less obvious.

The core difference from a user interface designer’s point of view between interaction with content on a desktop and a iPhone/iPad can be summed in a few words : cursor input versus touch input, much of what i will go on to detail stems from this, some of it might seem obvious but it is the obvious that is often forgotten.

1 – Hover

There is no hovering, your user interface can not depend on hovering to display tooltips, to visually highlight/select menu items, to show and hide dhtml dropdown menu’s, to underline links.

– hover tooltips are just gone, there is nothing you can do to replicate them.
– hover selecting/highlighting menu items is also something gone entirely.
– hiding and showing dropdown menu’s when hovering out/into has to be changed with a hide/show toggle on click events.
– differentiating textual links from normal text by wether they change when hovering over is gone, you have to make sure you do not rely on this differentiate textual links from static text.

Your browser does not support video, upgrade to a HTML5 compatible browser.

2 – Cursor

Well there isn’t any, cursor that is, traditionally the cursor changes shape depending on the type of the interface element under it, this gives important feedback to the user.

– the cursor does not change to the hand over clickable interface elements so you have to make sure the element reflects the fact that it is a clickable element

that it reflects what exactly is it’s clickable area, and that it’s clickable zone does not have blind spots

– the cursor does not change to the vertical bar that is the visual hint of a element that accepts text input below the cursor, so you have to make sure text input fields are distinctive.

There are a lot of other things to keep in mind besides these two major aspects, scrolling for example is different, page scrolling is performed by touching anywhere in the page, scrolling of distinct elements within the page has to be handled differently, there is also no pixel precision like on desktops and the element directly under the finger is obscured from view.