NSOperation 和 ARC 中 NSManagedObjectContext 保存方法上的 EXC_BAD_ACCESS,为啥?
Posted
技术标签:
【中文标题】NSOperation 和 ARC 中 NSManagedObjectContext 保存方法上的 EXC_BAD_ACCESS,为啥?【英文标题】:EXC_BAD_ACCESS on NSManagedObjectContext save method inside NSOperation and ARC, why?NSOperation 和 ARC 中 NSManagedObjectContext 保存方法上的 EXC_BAD_ACCESS,为什么? 【发布时间】:2012-02-23 18:33:09 【问题描述】:在打开 ARC 的情况下将 NSManagedObjectContext 保存在 NSOperation 中时,我发现了一些问题。没有ARC之前一切都很好。保存期间总是给出 EXC_BAD_ACCESS。代码如下所示:
//on the main thread
-(void)someFunc
array = ... //fetching an array of entities from a core data
for(SomeEntity * obj in array)
NSSomeOperation * op = [[NSSomeOperation alloc] initWithValue:[obj someField]];
//start an operation
//NSSomeOperation implementation
//...
- (void)main
//some code
NSError * error = nil;
[mainContext lock];
if (![mainContext save:&error]) //<--- HERE EXC_BAD_ACCESS
//process error
[mainContext unlock];
//some code
//...
使用 [mainContext setRetainsRegisteredObjects:YES] 和 objectWithID 不能解决此问题。
EXC_BAD_ACCESS(代码=1) EXC_BAD_ACCESS(代码=13)
-[__NSCFType contextDidSave:]: unrecognized selector sent to instance 0x7fc5c505d940
An observer of NSManagedObjectContextDidSaveNotification illegally threw an exception.
Objects saved =
inserted = "(\n)";
updated = "(\n <SomeEntity: 0x7fc5c55b6220> (entity: SomeEntity; id: 0x7fc5c5052b20 ... )";
and exception = -[__NSCFType contextDidSave:]: unrecognized selector sent to instance 0x7fc5c505d940 with userInfo = (null)
我使用单独的托管对象上下文并在此 NSOperation 中获取我的托管对象。
也许这与 Core Data 错误或 ARC 相关?也许ARC清理了一些必须保存的对象? 因为,没有 ARC,一切都很好,一切正常。当我打开 ARC - EXC_BAD_ACCESS。
有人知道为什么会这样吗?
【问题讨论】:
不,吉姆。这是在 NSOperation 内部,在另一个线程上。 好吧,我问的原因是因为你可以添加一个 NSOperation 到主队列(使用 NSOperationQueue mainQueue] addOperation:...]。如果这是在辅助线程或队列上,你在关注吗? Apple 文档使用单独的托管对象上下文,并将您的更改合并回主队列中的上下文? NSOperationQueue 在主线程上,是的。是的,我在 NSOperation 中创建了第二个 NSManagedObjectContext,但是在 init 方法中。并将更改与主 NSManagedObjectContext(在主线程上创建)上的 performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:) 合并。也许我需要在 NSOperation 的“main”方法中创建 NSManagedObjectContext 对象(第二个)? 看起来一切都是对的,如果它在主线程上的话。如果您已经在主线程上,则不需要 performSelectorOnMainThread,但这无关紧要。此外,如果它在主线程上,则使用 init 或 main 也没关系。 (对于必须在辅助线程上的工作,您应该使用 start 方法,但这与您描述的情况无关。) 如果您可以发布您的项目,我会看看它,看看我是否可以提出任何建议。 【参考方案1】:也许 ARC 释放了一些接收 NSManagedObjectContextDidSaveNotification 的对象,这会导致异常? 我有类似的东西,并通过确保在对象被释放之前 removeObserver: 来修复它。
请注意,CoreData 异常实际上隐藏了通知中心异常,因此您看不到它。
【讨论】:
谢谢Yonat!是的,你完全正确。我刚刚尝试删除Observer: - 它没有帮助。 我在共享上下文的单身人士的dealloc
中调用了removeObserver:
。删除dealloc
解决了问题,但我应该去哪里removeObserver
?
同时检查你是否多次调用 addObserver。经验法则是在 viewDidLoad 上执行,然后在 dealloc 上调用 removeObserver。以上是关于NSOperation 和 ARC 中 NSManagedObjectContext 保存方法上的 EXC_BAD_ACCESS,为啥?的主要内容,如果未能解决你的问题,请参考以下文章