Search code examples
objective-cios4grand-central-dispatchnsnotifications

How do I post a NSNotification when using Grand Central Dispatch?


I found that as predicted when I was writing an image to file that my UI was blocked for the duration, which was not acceptable. When I write the image to file I then post an NS Notification so that I can do some other specific jobs related to that completion. Original working but UI blocking code:

-(void)saveImageToFile {
    NSString *imagePath = [self photoFilePath];
    BOOL jpgData = [UIImageJPEGRepresentation([[self captureManager] stillImage], 0.5) writeToFile:imagePath atomically:YES];

if (jpgData) {        
    [[NSNotificationCenter defaultCenter] postNotificationName:kImageSavedSuccessfully object:self];
}

To avoid the UI blocking I have put the writeToFile: into a Grand Central Dispatch queue so it runs as a concurrent thread. But when the write is completed and the thread is done, I want to post an NSNotification. I cannot as the code is shown here because it is in a background thread. But that is the functionality I want to accomplish, realizing this is not workable code:

-(void)saveImageToFile {
    NSString *imagePath = [self photoFilePath];

    // execute save to disk as a background thread
    dispatch_queue_t myQueue = dispatch_queue_create("com.wilddogapps.myqueue", 0);
    dispatch_async(myQueue, ^{
        BOOL jpgData = [UIImageJPEGRepresentation([[self captureManager] stillImage], 0.5) writeToFile:imagePath atomically:YES];
        dispatch_async(dispatch_get_main_queue(), ^{
            if (jpgData) {        
            [[NSNotificationCenter defaultCenter] postNotificationName:kImageSavedSuccessfully object:self];
            }
        });
    });
}

What is the correct mechanism here to post this notification to gain the functionality I want ?


Solution

  • A couple possibilities here.

    1)

    How about [NSObject performSelectorOnMainThread: ...] ?

    E.G.

    -(void) doNotification: (id) thingToPassAlong
    {
        [[NSNotificationCenter defaultCenter] postNotificationName:kImageSavedSuccessfully object:thingToPassAlong];
    }
    
    -(void)saveImageToFile {
        NSString *imagePath = [self photoFilePath];
    
        // execute save to disk as a background thread
        dispatch_queue_t myQueue = dispatch_queue_create("com.wilddogapps.myqueue", 0);
        dispatch_async(myQueue, ^{
            BOOL jpgData = [UIImageJPEGRepresentation([[self captureManager] stillImage], 0.5) writeToFile:imagePath atomically:YES];
            dispatch_async(dispatch_get_main_queue(), ^{
                if (jpgData) {   
                    [self performSelectorOnMainThread: @selector(doNotification:) withObject: self waitUntilDone: YES];
                }
            });
        });
    }
    

    More details at http://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html#//apple_ref/occ/instm/NSObject/performSelectorOnMainThread:withObject:waitUntilDone:

    or 2)

    Completion Callbacks

    as seen at How can I be notified when a dispatch_async task is complete?