两个不同视图中的 NSManagedObjectContextObjectsDidChangeNotification 问题
大家晚上好,
在解释我的问题之前,我应该首先对我的项目进行一些解释:
我有一个简单的 Coredata 模型,其中一个实体称为“对话”,另一个实体称为“消息”。基本上,我需要重现 iPhone 短信应用程序。
Conversation{
messages<-->>Message.conversation
}
Message{
conversation<<-->Conversation.messages
}
正如您所看到的,我的模型很容易理解。几周前,我询问了一些关于如何完全实现这些视图的帮助(即使用 NSFetchedResultsController (FRC) 或不在视图中显示来自 这篇文章。
所以我所做的是在每个视图中使用一个 FRC。另一个线程是不时更新我的模型。为了通知我的视图我的模型发生了变化,我在第二个线程中使用了它:
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self
selector:@selector(mergeChanges:)
name:NSManagedObjectContextDidSaveNotification
object:_context];
并且 mergeChanges: 函数正在这样做:
- (void)mergeChanges:(NSNotification *)notification {
AppDelegate *appDel = (AppDelegate*)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *mainContext = [appDel managedObjectContext];
// Merge changes into the main context on the main thread
[mainContext performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:)
withObject:notification
waitUntilDone:YES];
}
我认为这段代码工作得很好,因为在两个 viewController 中(让称它们为ConversationVC(其中列出了每个对话)和MessageVC(其中列出了特定对话中的每条消息)),我使用:
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller;
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath;
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller;
我的问题如下:
当我在第二个线程中插入新消息并保存上下文时,即使未显示 MessageVC,通知也会发送到两个视图。它不是我的 ConversationVC 的属性,因此当它被弹出时,它的值应该为零。 (我认为)。
我的问题是:为什么将其发送到未显示的视图?我在调试器中的任何地方都看不到它的值。我尝试将其设为视图的属性,然后在返回 ConversationVC 时为其分配“nil”,但随后收到 SIGBRT 错误,指出通知已发送到已释放的变量(这是合乎逻辑的)。
我真的需要它只发送到当前显示的视图。 你有什么想法吗?
非常感谢
Good evening everyone,
before explaining my problem, I should give you some explanation on my project first :
I have a simple Coredata model with one entity called "Conversation" and the other one "Message". Basically, I need to kind of reproduce the iPhone sms application.
Conversation{
messages<-->>Message.conversation
}
Message{
conversation<<-->Conversation.messages
}
As you can see, my model is easy to understand. I asked some help a few weeks ago about how to implement these views altogether (i.e. using NSFetchedResultsController (FRC) or not in the view displaying messages from a specific conversation on this post.
So Wh at i did is that I use one FRC in each view. Another thread is from time to time updating my model. In order to notify my views that my model changed, I used this in my second thread :
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self
selector:@selector(mergeChanges:)
name:NSManagedObjectContextDidSaveNotification
object:_context];
And the mergeChanges: function is doing this :
- (void)mergeChanges:(NSNotification *)notification {
AppDelegate *appDel = (AppDelegate*)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *mainContext = [appDel managedObjectContext];
// Merge changes into the main context on the main thread
[mainContext performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:)
withObject:notification
waitUntilDone:YES];
}
This code was I thought working great because in both viewController (lets call them ConversationVC (where every conversations are listed) and MessageVC (where every messages from a specific conversations are listed)), I used :
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller;
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath;
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller;
My Problem however is the following :
When I'm inserting new messages in my second thread and the context is saved, the notification is sent to both views, even if the MessageVC is not being displayed. It's not a property of my ConversationVC so when it gets poped, its value should be nil. (I think).
My question is : why is this sent to a view not being displayed ? I can't see it's value in the debugger anywhere. I tried to make it a property of the view and then assigned "nil" to it when coming back to the ConversationVC, but then I get a SIGBRT error saying that the notification was sent to a deallocated variable (which was logical).
I really need it to be sent only to the view currently displayed.
Do you have any idea ?
Thank you very much
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
好吧...让我问一个问题:视图是否先显示然后隐藏 - 即您是否忘记告诉它停止观察通知?
Okay... let me ask one question: does the view get displayed and THEN hidden - i.e. did you forget to tell it to STOP observing the notifications?
这可能会帮助一些人:
对于这个问题,我没有忘记调用 [NSNotificationCenter removeObserver:] 因为我正在谈论的方法在哪里:
这些方法属于 NSFetchedResultsControllerDelegate。基本上,每当对 CoreData 进行更改,并且您的 NSFetchedResultsController 绑定到更改的数据时,都会以某种方式调用委托,并调用这三个方法。
我所做的是:
像这样,如果它被调用,消息将被发送到 nil(已授权),而不是发送到已释放的实例变量。
This might help some people :
For that issue, I didn't forget to call [NSNotificationCenter removeObserver:] because the method I was talking about where :
These methods belongs to the NSFetchedResultsControllerDelegate. Basically, whenever a change is made to CoreData, and that your NSFetchedResultsController binds on the changed data, the delegate is called somehow, and calls these three methods.
What I did was :
like that, if it gets called, the message will be sent to nil, which is authorized, and not to a deallocated instance variable.