refresher on resource forks

Resource forks are a strange beast, while Apple started moving away from them (around 10.4) and migrated to HFS Attributes, software like Adobe’s Photoshop still save (can be disabled in Preferences > File Handling) file previews as resource forks, here is a refresher on how to view, find and delete resource forks.

You can see is a file has a resource fork in a number of ways (they all involve the terminal)

1- see if the file has a “com.apple.ResourceFork” extended attribute

xattr /Volumes/Volumename/Dirname/filename.extension

2- lookup the attributes of the resource fork directly

ls -l@ /Volumes/Volumename/Dirname/filename.extension

ls -ila /Volumes/Volumename/Dirname/filename.extension/..namedfork/rsrc

File system operations can be performed on a resource fork just like any other file so you can copy or delete them, to get a path to the resource fork you add /..namedfork/rsrc to the full path of the file in question, for example to copy then remove the fork:

cp /Volumes/Volumename/Dirname/filename.extension/..namedfork/rsrc ~/Desktop/thefork.rsrc

rm /Volumes/Volumename/Dirname/filename.extension/..namedfork/rsrc

You can also delete the fork by removing the extended attribute

xattr -d com.apple.ResourceFork /Volumes/Volumename/Dirname/filename.extension

Or print a hex dump of the actual data in the fork

xattr -l com.apple.ResourceFork /Volumes/Volumename/Dirname/filename.extension

You can find all the files that have resource forks with this terminal command :

find / -type f -exec test -s {}/..namedfork/rsrc ; -print

Now if you were to combine the last two you could delete all resource forks (in a given type of files under a certain path) e.g.:

find /Volumes/Volumename/Dirname -type f -name “*.extension” -exec test -s {}/..namedfork/rsrc ; -print0 | xargs -0 xattr -d com.apple.ResourceFork

 

NOTES:
Messing around with/deleting resource forks should be pretty safe nowadays, they were the mechanism used in Snow Leopard for storing HFS compressed files but this has been removed altogether in Lion.

The actual file as we know it is referred to as the data fork in this context and there used to be a way to get to it with /..namedfork/data but that does not appear to work anymore, if anyone can clarify please comment.

If you want to really dig into the gory details of your filesystem or maybe are in the unfortunate predicament of having to recover lost data i strongly recommend fileXray by Amit Singh, writer of the Mac OS X Internals book.

getting positive software feedback

It has been proven that the drive to give feedback on something is strongly polarized, that is the feedback is shaped by strong feelings either positive or negative, which makes sense, the people with median feelings do not care enough to give feedback, it should come as no surprise that this mechanic is relevant to getting positive feedback, basically to get positive feedback you want engagement, for people to care enough to say something, once you have that positive feedback is a given.

Negative feedback is inevitable, a user’s hardware or operating system could be defective, tampered by factors like jailbreaking/hacking or the feedback could be plain untruthful by either confusion or spambots/competitor malevolence, either way there will always be some, you might as well accept it.

However that inherent negative feedback is limited in scale, positive feedback can easily outpace it if there is any drive for the users to feel the need to express anything positive, what you want to do is instill that drive for positive feedback, those that have median feelings will not engage at all, it is only the poles of the spectrum that will generally be the source of most feedback.

Unless you have a serious problem that causes significant feedback all negative, just a little engagement to outweigh that inherent negative feedback will always tip the scale towards positive, with no engagement that little negative feedback is all you get.

Sandboxing woes

It’s a brave new sandboxing world they say and that brings about many implications good and bad, to a security professional asking the user for permission to read every single file might be pure heaven, to a UX professional it might be hell.

Either way consider this scenario, you have a application that needs to know some operating system setting, some configuration context, Apple can never provide exhaustive API’s for all scenarios and you will inevitably have to read or write to files the user does not directly need to interact with.

Before sandboxing you could just do this transparently, this is all good unless a attacker takes over your application and leverages it to wreak havoc, that is what sandboxing prevents but it also prevents legitimate scenarios and until Apple adds a way to specify in the entitlements a list of files that the application transparently needs to access the only way is to ask the user explicit permission.

Here is a way :

-(void)punchHoleInSandboxForFile:(NSString*)file
{
    //only needed if we are in 10.7
    if (floor(NSAppKitVersionNumber) < = 1038) return;
    //only needed if we do not allready have permisions to the file
    if ([[NSFileManager defaultManager] isReadableFileAtPath:file] == YES) return;
    //make sure we have a expanded path
    file = [file stringByResolvingSymlinksInPath];
    NSString *message = [NSString stringWithFormat:@"Sandbox requires user permision to read %@",[file lastPathComponent]];

    NSOpenPanel *openDlg = [NSOpenPanel openPanel];
    [openDlg setPrompt:@"Allow in Sandbox"];
    [openDlg setTitle:message];
    [openDlg setShowsHiddenFiles:NO];
    [openDlg setTreatsFilePackagesAsDirectories:YES];
    [openDlg setDirectoryURL:[NSURL URLWithString:file]];
	[openDlg setCanChooseFiles:YES];
	[openDlg setCanChooseDirectories:NO];
	[openDlg setAllowsMultipleSelection:NO];
	if ([openDlg runModal] == NSOKButton){
        NSURL *selection = [[openDlg URLs] objectAtIndex:0];
        if ([[[selection path] stringByResolvingSymlinksInPath] isEqualToString:file]) {
            return;
        }else{
            [[NSAlert alertWithMessageText:@"Wrong file was selected." defaultButton:@"Try Again" alternateButton:nil otherButton:nil informativeTextWithFormat:message] runModal];
            [self punchHoleInSandboxForFile:file];
        }
	}else{
        [[NSAlert alertWithMessageText:@"Was denied access to required files." defaultButton:@"Carry On" alternateButton:nil otherButton:nil informativeTextWithFormat:@"This software can not provide it's full functionality without access to certain files."] runModal];
    }
}

You need to add a call to punchHoleInSandboxForFile before every file access call eg:

[self punchHoleInSandboxForFile:@"/etc/hostconfig"];
NSString *stuff = [[NSString alloc] initWithContentsOfFile:@"/etc/hostconfig"];

This nags the user once for each file, once the hole has been punched for that file it persists for the lifetime of the process, it presents a file dialog with the file in question already selected (however that does not seem to be consistent, sometimes selecting the file will be required) .

Here’s hoping Apple adds something along the lines of setting specific files with permissions in the entitlements sooner than later, until then feel free to use this and suggest any better alternatives you can find.

 

Off by 7%

I noticed something quite strange today, almost a year since Apple launched their Magic Trackpad their marketing materials on the website do not depict the actual device correctly in terms of proportions.

Don’t get me wrong, a 7% width difference from the promotional images to that of the actual device is a far cry from deceptive marketing and had it been any* other company than Apple such a slip up would not even worth mentioning, but i find it quite notable given how notorious Apple is for the attention to detail in both products and marketing going as far as to depict the exact time that Steve Jobs introduced the iPhone on all iPhone marketing materials.

Here is how the images on apple.com/magictrackpad/ compare to a image of a actual Magic Trackpad, all images show it 7% wider, and it is not that they do not have images of the hands on properly sized Magic Trackpads, boxes for it from the initial US version and the current EU version both show accurate sized devices.

*Take ViewSonic for example that had OSX depicted running on their ViewPad tablet‘s promotional materials

discrete graphics and you

In 2010 Apple introduced a feature in MacBooks with the aim of extending battery life “Automatic graphics switching” that switches between using either the integrated Intel GPU  inside the CPU or the standalone discrete AMD/Nvidia GPU.

The exact conditions however that make it switch one or the other were never clearly stated by Apple, and there has been much debate confusion and speculation on the subject.

Upon testing i found the answer to be pretty straight forward in that if a application ever loads the OpenGL.framework the machine switches to the standalone GPU (easiest way to determine this is inspect the files area of the program with Activity Monitor and look for OpenGL.framework) ,i have so far unable to find any other framework besides it to trigger the switch.

Determining what can make it load that framework is not that straight forward however, and remember it does not have to be linked for it to be loaded, any API that relies on it can trigger it’s loading, and the likely culprit in most cases will be Core Animation which uses OpenGL backing.

So to make sure you do not trigger the standalone GPU you need to make sure your code does not rely on any Core Animation API’s or any that otherwise uses OpenGL, also remember that all the “Effects” in Interface Builder require a Core Animation layer that will trigger the loading of the OpenGL.framework

EDIT: As of lion there is a property you can control this behavior with, the NSSupportsAutomaticGraphicsSwitching key as detailed in the Allowing OpenGL applications to utilize the integrated GPU QA

 

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.

iphone signal testing with code

Closest cell tower 1 Km, iPhone 3G, Wi-fi mode, iOS 4.0, Orange network.

With device held gently by edges:

signal avg 90 (outdoor, line of sight to cell tower, same altitude)
signal avg 😯 (indoor, line of sight to cell tower, same altitude)
signal avg 60 (indoor, no line of sight to cell tower, same altitude)
signal avg 4O (outdoor, no line of sight to cell tower, ground level)

With device cradled in hand a average decrease of signal by about 20 in all cases and whatever finger configuration.

Turning 3G on causes a average decrease of signal by 5 in all cases.

The connection strength bars shows 5 bars in all cases.

Absolute minimum experienced : 19, absolute maximum 96.

The thing to take away from all this is that if  you already had a very bad connection under 20 and subtract the hand attenuation of about 20 you are left with no signal, and it did not hep that until iOS 4.0.1  a bad connection with a 20 strength would have shown 4 or even 5 bars.

The application used to test gets the signal strength from private calls to apple’s CoreTelephony framework, in a effort to help the iphone signal testing going on share a common base i am providing the application to anyone, please let me know what are the results of your tests and feel free to contribute to the code on github.

The application is named  VAFieldTest , it’s code is under a open source license and can be found at http://github.com/valexa/VAFieldTest , you need Xcode and a iPhone developer account to compile and run it.

iOS 4.0.1 update
same behavior as before, with the difference that now the connection bars properly reflect changes in the strength (I 1-19, II 20-29, III 30-39, IIII 40-49, IIIII 50-99 ) , with previous versions they just show 5 bars for any signal strengths above 25.