当我尝试从背景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];
}
所以我把这个班级作为观察者解开了。在我看来,它不应该尝试合并任何未分配的实例上的更改。虽然当我再次触摸该行时,虽然我试图将更改合并到我的控制器的第一个实例中,但是我还是相信,即使我已经停止订阅该通知。
我很难过。任何帮助将不胜感激。
答案 0 :(得分:1)
您是否正在使用fetchedResultsControllerDelegate?
如果是,请确保在视图消失或卸载时将其设置为nil,否则无论移除观察者,它都将继续接收有关数据更改的消息。
答案 1 :(得分:0)
一个应该有帮助的快速更正是[super dealloc]
始终应该是dealloc
中的最后一个语句。
此外,由于您正在后台线程上执行CoreData操作(通过NSOperationQueue
),因此请确保在后台线程中为后台线程对象创建NSManagedObjectContext
。不要在一个线程上创建它并将其分配给将在不同线程中运行的对象,否则您将遇到各种各样的问题。
当您收到NSManagedObjectContextDidSaveNotification
通知时,您需要在合并到的上下文所属的同一个线程上进行合并。很可能这将是你的主要上下文(听起来像)你的app委托,这意味着它在主线程上。