尝试清除和保存不同的上下文时访问权限不佳

时间:2015-09-23 11:05:22

标签: ios core-data concurrency grand-central-dispatch nsmanagedobjectcontext

我需要定期更新我在Core Data时保留的数据。我从REST服务的异步调用中获取此类数据。首先检索所有数据,我在私有队列中创建一个完整的核心数据堆栈然后我这样做:

- (void)updateDataFromServices
{
   [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
   self.dataUpdatePrivateContext = [MyCoreDataStackHelper getPrivateContext];

   if (self.dataUpdatePrivateContext != nil) {
       [self.dataUpdatePrivateContext performBlockAndWait: ^{
           // Asynchronous operations
           [self callService1];
           [self callService2];
           [self callService3];
       }];
   }
}

在每个被调用的服务的回调中,我检查其余的服务是否已经完成,如果一切都已完成,我调用一个方法(manageInfoUpdate)来处理我所拥有的数据之间的更新我的主要上下文(在主线程中)和我现在在私有上下文中(在私有队列中)的数据:

- (void)manageInfoUpdate
{
   const char* UpdateInfoQueue = "com.comp.myapp.updateinfo";
   dispatch_queue_t queue = dispatch_queue_create(UpdateInfoQueue, NULL);
   dispatch_async(queue,^{

    // Handle updates from private context:
    // Here I compare objects in the main context with the objects
    // in the private context and I delete objects from both
    // by calling:

    [mainContext deleteObject:object];
    [self.dataUpdatePrivateContext deleteObject:object];
    // This seems to work...

    // Save and clear private context
    [self saveContext:self.dataUpdatePrivateContext];
    [self clearContext:self.dataUpdatePrivateContext];

    dispatch_async(dispatch_get_main_queue(), ^{
        // Re-fetch from main context to get
        // the updated data

        // Save main context
        [self saveContext:mainContext];

        // Notify end of updates
    });
});
}

我尝试在另一个异步线程中执行manageInfoUpdate操作。我试图清除/保存上下文时遇到EXEC_BAD_ACCESS例外...有人可以帮我找到原因吗?

提前致谢

1 个答案:

答案 0 :(得分:1)

如果错误地在多线程环境中使用Core Data,您将无法获得彻底的“错误”。该应用程序有时会崩溃。

要确认您正确使用它,请在运行时参数中打开调试标志com.apple.CoreData.ConcurrencyDebug 1。然后,当你从错误的队列中触摸MOC或MO时,它会崩溃。

就目前而言,您的代码在线程方面根本不正确。只能从该队列访问在一个队列上创建的MO。同样,必须在主队列上访问为主队列配置的MOC,并且必须在 ITS 专用队列上访问配置为专用队列的MOC。

您的“UpdateInfoQueue”完全违反了线程规则。

打开调试标志,更正它显示的错误,您的保存问题将得到纠正。