id self = (id)0x1 for Block Debugging

I’ve just been bitten again by how easy it is to accidentally retain self using Objective-C blocks.

After a little thought, I came up with a single line of code you can place in the header of your block that will root out most (all?) possible errors: id self = (id)0x1.

Here it is in action:

@implementation MyClass
@synthesize window;

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    __block typeof(self) blockSelf = self;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1ull * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
        id self = (id)0x1;          // SHOULD result in compile-time warning: "unused variable 'self'"

        blockSelf.window;           // Fine
        self.window;                // Compile-time error: "request for member 'window' in something not a structure or union"
        window;                     // Compile-time error: "'struct objc_object' has no member named 'window'"

        NSLog(@"%@", blockSelf);    // Fine
        NSLog(@"%@", self);         // No compile-time warnings or errors, but runtime EXC_BAD_ACCESS
    });
}

@end

objc block blocks debugging Mar 16 2011