2011-10-06 96 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];即主線程。

相關問題