CoreData合并改变怪异

时间:2011-12-17 05:10:35

标签: ios core-data nsmanagedobjectcontext

当我尝试从背景NSOperation合并我的更改时,我遇到了一个奇怪的僵尸对象问题:

(controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:]: message sent to deallocated instance) 

我有一个ViewController推送navController AppDelegate堆栈中的didSelectRowForIndexPath堆栈上的其他控制器,如下所示:

ABCViewController *myVC = [[ABCViewController alloc] initWithNibName:@"ABCViewController" bundle:nil];

ABCEvent *selectedEvent = [_fetchedResultsController objectAtIndexPath:indexPath];
[myVC setManagedObjectContext:[self managedObjectContext]];
[myVC setTitle:@"Title"];
[myVC setEvent:selectedEvent];

ABCAppDelegate *appDelegate = (ABCAppDelegate *)[[UIApplication sharedApplication] delegate];
[[appDelegate navController] pushViewController:myVC animated:YES];
[myVC release];

然后在我的ViewDidLoad ABCViewContoller我正在创建一个操作队列,并将后台操作添加到其中:

_operationQueue = [[NSOperationQueue alloc] init];

除了挂钩通知以便我可以合并更改:

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(contextDidSave:)
                                             name:NSManagedObjectContextDidSaveNotification
                                           object:nil];

我相信所有标准的东西。问题是如果我选择主VC中的行,然后返回到它,再次点击该行,我得到:消息发送到解除分配的实例消息。现在,如果我关闭NSManagedObjectContextDidSaveNotification的通知,那么我没有得到错误,所以这绝对是罪魁祸首。我的第二个控制器中的dealloc是这样的:

- (void)dealloc
{
    [super dealloc];
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [_operationQueue release];
}

所以我把这个班级作为观察者解开了。在我看来,它不应该尝试合并任何未分配的实例上的更改。虽然当我再次触摸该行时,虽然我试图将更改合并到我的控制器的第一个实例中,但是我还是相信,即使我已经停止订阅该通知。

我很难过。任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:1)

您是否正在使用fetchedResultsControllerDelegate?

如果是,请确保在视图消失或卸载时将其设置为nil,否则无论移除观察者,它都将继续接收有关数据更改的消息。

答案 1 :(得分:0)

一个应该有帮助的快速更正是[super dealloc] 始终应该是dealloc中的最后一个语句。

此外,由于您正在后台线程上执行CoreData操作(通过NSOperationQueue),因此请确保在后台线程中为后台线程对象创建NSManagedObjectContext 。不要在一个线程上创建它并将其分配给将在不同线程中运行的对象,否则您将遇到各种各样的问题。

当您收到NSManagedObjectContextDidSaveNotification通知时,您需要在合并的上下文所属的同一个线程上进行合并。很可能这将是你的主要上下文(听起来像)你的app委托,这意味着它在主线程上。