12

我很困惑爲什麼在下面的代碼中永遠不會刪除觀察者。在我的viewDidAppear我有以下幾點:爲什麼不從NSNotificationCenter中刪除觀察者:addObserverForName:usingBlock被調用

-(void)viewDidAppear:(BOOL)animated{ 

id gpsObserver = [[NSNotificationCenter defaultCenter] 
          addObserverForName:FI_NOTES[kNotificationsGPSUpdated] 
          object:nil 
          queue:[NSOperationQueue mainQueue] 
          usingBlock:^(NSNotification *note){ 

           NSLog(@"run once, and only once!"); 

       [[NSNotificationCenter defaultCenter] removeObserver:gpsObserver]; 

     }]; 

} 

觀察員永遠不會被刪除,語句是輸出每次通知發出的時間。任何人都可以提供指導嗎?

回答

28

當通過addObserverForName:將塊壓入堆棧時,該方法尚未返回,因此gpsObserver爲零(在ARC下)或垃圾/未定義(不在ARC下)。在外部聲明使用__block的變量,這應該起作用。

__block __weak id gpsObserver; 

gpsObserver = [[NSNotificationCenter defaultCenter] 
          addObserverForName:FI_NOTES[kNotificationsGPSUpdated] 
          object:nil 
          queue:[NSOperationQueue mainQueue] 
          usingBlock:^(NSNotification *note){ 

           NSLog(@"run once, and only once!"); 

       [[NSNotificationCenter defaultCenter] removeObserver:gpsObserver]; 

     }]; 

我已經添加了__weak以確保沒有內存泄漏(按照Matt的回答)。代碼未經測試。

+0

這是有道理的,並按預期工作;感謝您的幫助。 – warpedspeed

11

我發現實際上存在內存泄漏,除非觀察者同時標記爲__block__weak。使用儀器確保self不被過度保留;我敢打賭。然而,這是正確的(從我的實際代碼):

__block __weak id observer = [[NSNotificationCenter defaultCenter] 
    addObserverForName:@"MyMandelbrotOperationFinished" 
    object:op queue:[NSOperationQueue mainQueue] 
    usingBlock:^(NSNotification *note) { 
     // ... do stuff ... 
     [[NSNotificationCenter defaultCenter] 
      removeObserver:observer 
      name:@"MyMandelbrotOperationFinished" 
      object:op]; 
}]; 
+0

我很喜歡它,如果他們會介紹等價的方法,實際上不需要你堅持觀察者,而是將自己作爲一個整體,只需使用塊而不是選擇器。 – Eugene

+2

如果您從'NSNotificationCenter'中移除它後將其設置爲'nil',則不需要設置'observer' __weak'。我用儀器檢查過。 –

+0

這是一段很好的代碼,先生。 – Andy

相關問題