This question is similar to this question with automatic reference counting thrown in.
I have an NSOperation subclass that accepts a block argument that is intended as a callback to the main (UI) thread. My original intention was to perform some operation in the background, and then use dispatch_async and the main queue to perform the callback.
Original premise:
@interface MySubclass : NSOperation {
@protected
    dispatch_block_t _callback;
}
- (id)initWithCallback:(dispatch_block_t)callback;
@end
@implementation MySubclass
- (void)main
{
    // Do stuff
    if (![self isCancelled]) { 
        dispatch_async(dispatch_get_main_queue(), _callback);
    }   
}
@end 
Problems arise when all references to a UIKit object outside the scope of the block are removed. (E.g. a UIViewController is popped off a navigation stack.) This leaves the only reference to the object inside the block, so the object is deallocated when the block is, on the thread where the block is deallocated.  Deallocating a UIKit object off the main thread crashes the app with the error message Tried to obtain the web lock from a thread other than the main thread or the web thread. This may be a result of calling to UIKit from a secondary thread. Crashing now...
As a workaround, I added a __block modifier to the callback ivar, and am using dispatch_sync to make sure everything released is on the main thread.
@interface MySubclass : NSOperation {
@protected
    __block dispatch_block_t _callback;
}
- (id)initWithCallback:(dispatch_block_t)callback;
@end
@implementation MySubclass
- (void)main
{
    // Do Stuff
    if (![self isCancelled]) {
        dispatch_block_t block = ^{
            _callback();
            _callback = nil;
        };
        // Cover all our bases to prevent deadlock
        if ([NSThread isMainThread]) block();
        else dispatch_sync(dispatch_get_main_queue(), block);
    }
}
@end
I am wondering if there is a better way to accomplish something with this premise. My workaround feels hacky, and I don't like that I might end up with several operations in my queue all waiting for a turn on the main thread before they can complete.