2015-10-16 94 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变量能够使用它的观察者被触发时执行块内。