您好我有一个FriendsViewController,我在其中显示从coreData获取的朋友记录。我有另一个View Controller AddFriendViewController由FriendsViewController提供,以添加一个新的朋友,它将Context保存在其中。我正在收听FriendsViewController中共享MOC上的更改通知。
[[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,因为我使用UILocalizedIndexedCollation将我的数组排序到部分。所以我的问题是为什么它被召唤两次,有时甚至三次?或者有其他替代方案吗?
答案 0 :(得分:1)
只有您知道希望通知观察者何时处于活动状态。
然而,两种常见的范例是:
如果您希望在视图控制器的生命周期内随时收到通知,请在viewDidLoad
中注册观察者并删除dealloc
中的观察者。
如果您希望在视图处于有效状态时收到通知,请在viewWillAppear
中注册观察者并在viewWillDisappear
中删除。
修改强>
我使用此语句删除所有条目[[NSNotificationCenter defaultCenter] removeObserver:自];它仍然显示相同 行为。然后我使用了addObserver:selector:name:object:方法 哪个有效。但为什么另一个没被删除? - 阿萨杜拉·阿里
那是因为你添加了一个基于块的观察者,它返回一个观察者对象。您删除它返回给您的对象。您真的应该阅读您使用的每种方法的文档。
如果使用block-observer方法,则添加/删除将如下所示。
id observer = [[NSNotificationCenter defaultCenter]
addObserverForName:SomeNotification
object:objectBeingObserved
queue:nil
usingBlock:^(NSNotification *note) {
// Do something
}];
[[NSNotificationCenter defaultCenter] removeObserver:observer];
如果使用selector-observer方法,则需要删除为add调用提供的观察者。
[[NSNotificationCenter defaultCenter]
addObserver:someObject
selector:@selector(notificationHandler:)
name:SomeNotification
object:objectBeingObserved];
[[NSNotificationCenter defaultCenter]
removeObserver:someObject
name:SomeNotification
object:objectBeingObserved];
答案 1 :(得分:1)
首先,我强烈建议使用NSFetchedResultsController
而不是建立自己的观察者。
其次,听起来好像你要多次添加观察者。您应该将其添加到-viewDidLoad
中,然后将其移除-dealloc
。
同样,NSFetchedResultsController
是更好的解决方案。你将获得更好的表现并避免像你现在所做的那样重新获得。
答案 2 :(得分: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
变量中,以便能够在触发观察者时执行的块内使用它。