2011-10-06 95 views
3

我发现,正如我在编写图像时所预测的那样,我的UI在持续时间内被阻止,这是不可接受的。当我将图像写入文件时,我会发布NS通知,以便我可以完成与该完成相关的其他特定工作。原来的工作,但UI阻止代码:如何在使用Grand Central Dispatch时发布NSNotification?

-(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]; 
} 

为了避免阻塞UI我已经把将writeToFile:进入大中央调度队列所以它运行的并发线程。但是当写入完成并且线程完成时,我想发布一个NSNotification。我不能在这里显示代码,因为它在后台线程中。但是,这是我要完成的功能,实现这不是可行代码:

-(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]; 
      } 
     }); 
    }); 
} 

这里正确的机制来发布该通知,以获得我想要的功能是什么?

回答

6

这里有几种可能性。

1)

如何[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]; 
      } 
     }); 
    }); 
} 

更多细节在http://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html#//apple_ref/occ/instm/NSObject/performSelectorOnMainThread:withObject:waitUntilDone

或作为How can I be notified when a dispatch_async task is complete?

+0

我认为您的第一个选项的简单性非常干净清晰。我不知道performSelectorOnMainThread :.指出子线程并在主循环中执行工作是一种很好的方式。很好。谢谢。 – Ric

+0

原始问题中的代码不起作用吗?它看起来应该像预期的那样工作,因为您正在将通知分派到传递给'myQueue'的块末尾的主队列。我更喜欢使用'performSelector:onMainThread:'这个模式,因为你没有编写一个单独的方法来处理你的通知。清洁代码IMO。 – sho

+0

所以我现在困惑与所有选项。 NSNotificationCenter,GrandCentralDispatch-Blocks和performSelectorOnMainThread。我用NSOperation&Queue使用了pSOMT,但从来没有使用前两个。有人能解释一下这些差异或优点吗? – marciokoko

1
-(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]; 
      } 
     }); 
    }); 
} 

这已经是正确的看到2)

完成回调

。但是,如果您已经是dispatch_get_main_queue(),为什么还需要使用通知?

只需使用

 dispatch_async(dispatch_get_main_queue(), ^{ 
      if (jpgData) {   
      //Do whatever you want with the image here 
      } 
     }); 

反正你原来的解决方案是好的。它没有阻塞。基本上它会将文件保存在其他线程中,一旦完成,它将完成所需的工作。你在做什么都可以在同一个线程上完成,调用[[NSNotificationCenter defaultCenter] postNotificationName:kImageSavedSuccessfully object:self];即主线程。

相关问题