2015-10-16 89 views
1

嗨,我有一個FriendsViewController,我顯示從coreData獲取的朋友記錄。我有另一個視圖控制器AddFriendViewController這是由FriendsViewController添加一個新的朋友,它保存在其中的上下文。我正在收聽FriendsViewController中共享MOC的更改通知。多次調用NSManagedObjectContextDidSaveNotification

[[NSNotificationCenter defaultCenter] 
addObserverForName:NSManagedObjectContextDidSaveNotification 
object:appdelegate.context queue:nil 
usingBlock:^(NSNotification * _Nonnull note) { 
        NSLog(@"Re-Fetch Whole Friends Array from core data and Sort it with UILocalizedIndexedCollation and reloadData into table"); 
       }]; 

在AddFriendsViewController只需要創建一個朋友的對象,我

Friend *friend= [NSEntityDescription 
       insertNewObjectForEntityForName:@"Friend" 
       inManagedObjectContext:appdelegate.context]; 
friend.name=nameTextfield.text; 
[appdelegate.context save:&error]; 
[self.navigationController popViewControllerAnimated:YES]; 

現在,當我執行節省從AddFriendViewController上下文中FriendsViewController上述塊被觸發幾次,而不是一個時間這會導致更多的處理,因爲從核心數據中重新獲取整個數據。我無法使用Fetched Results Controller,因爲我使用UILocalizedIndexedCollat​​ion將我的數組排序。所以我的問題是爲什麼它被稱爲兩次或有時甚至三次?或者有沒有其他辦法呢?

+0

你有沒有機會使用多個託管對象上下文,並且它們之間有父/子關係? –

+0

我已經想通了,我必須刪除這個觀察者,我在didLoad中添加了這個觀察者,但不知道在哪裏刪除它? PS。我在這個視圖控制器後面有一個視圖控制器,所以每當我回到這個視圖時再添加一個觀察者。 –

回答

1

只有您知道何時希望通知觀察者處於活動狀態。

但是,有兩個共同的範式是:

如果你想成爲視圖控制器的使用壽命期間隨時通知,那麼您註冊觀察員viewDidLoad和刪除觀察員dealloc

如果您希望隨時通知該視圖處於活動狀態,請在viewWillAppear中註冊觀察員並在viewWillDisappear中刪除。

編輯

我用這個語句刪除所有條目[NSNotificationCenter defaultCenter] removeObserver:自我]。它仍然顯示出相同的行爲 。然後,我使用addObserver:selector:name:object:method which worked。但爲什麼另一個沒有被刪除? - Asadullah Ali

這是因爲你添加了一個基於塊的觀察者,它返回一個觀察者對象。你刪除它返回給你的對象。你真的應該閱讀你使用的每種方法的文檔。

如果使用block-observer方法,add/remove將如下所示。

id observer = [[NSNotificationCenter defaultCenter] 
    addObserverForName:SomeNotification 
       object:objectBeingObserved 
       queue:nil 
      usingBlock:^(NSNotification *note) { 
    // Do something 
}]; 

[[NSNotificationCenter defaultCenter] removeObserver:observer]; 

如果使用selector-observer方法,則需要刪除提供給add call的觀察者。

[[NSNotificationCenter defaultCenter] 
    addObserver:someObject 
     selector:@selector(notificationHandler:) 
      name:SomeNotification 
     object:objectBeingObserved]; 

[[NSNotificationCenter defaultCenter] 
    removeObserver:someObject 
       name:SomeNotification 
      object:objectBeingObserved]; 
+0

我注意到觀察者添加了這個方法addObserverForName:object:queue:usingBlock:不會在dealloc方法中被刪除。 –

+0

我用這個語句刪除所有條目[[NSNotificationCenter defaultCenter] removeObserver:self];它仍然表現出相同的行爲。然後我使用了addObserver:selector:name:object:方法。但爲什麼另一個沒有被刪除? –

+0

是這個總結。謝謝 –

1

首先,我會強烈建議使用NSFetchedResultsController,而不是建立自己的觀察員。

其次,聽起來就像你多次添加觀察者。您應該將其添加到-viewDidLoad中,並在-dealloc中將其刪除。

同樣,NSFetchedResultsController是更好的解決方案。你會有更好的表現,並避免像現在這樣做的重新調整。

+0

我很喜歡使用NSFetchedResultsController,因爲我在其他TableViewControllers或ViewControllers中使用它。但我不能在這裏使用它,因爲我必須支持不同語言的名稱(中文,英文,在我的情況下)使用SectionIndexTitle進行排序我努力嘗試,但最終這樣做。如果您可以建議其他方式使用FRC進行中文和英文排序,將不勝感激。參考:http://stackoverflow.com/questions/7199934/nsfetchedresultscontroller-v-s-uilocalizedindexedcollat​​ion –

+0

我注意到觀察者添加了此方法addObserverForName:對象:隊列:usingBlock:不會在dealloc方法中刪除。 –

+0

塊觀察員有一些問題。我不推薦使用它。 –

0

你必須擺脫觀察者(正如其他人已經在此陳述)。最簡單的方法是使用「一次性觀察者」,當其被激活時自行移除。在您的示例代碼,這將是這樣的:

id __block observer; 
observer = [[NSNotificationCenter defaultCenter] 
      addObserverForName:NSManagedObjectContextDidSaveNotification 
      object:[PubStore sharedStore].managedObjectContext queue:nil    
      usingBlock:^(NSNotification * _Nonnull notification) { 
       [[NSNotificationCenter defaultCenter] removeObserver:observer]; 
       NSLog(@"Re-Fetch Whole Friends Array from core data and Sort it with UILocalizedIndexedCollation and reloadData into table"); 
      }]; 

注意,您必須觀察者存儲在__block變量能夠使用它的觀察者被觸發時執行塊內。