将dispatch_async与Core Data一起使用时获取EXC_BAD_ACCESS

diz*_*izy 5 iphone core-data objective-c grand-central-dispatch automatic-ref-counting

我在coredata中有图像,我试图懒洋洋地加载表格视图.每个单元使用相关核心数据实体的观察者在可用时更新图像.实体中的相关代码如下:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  // The heavy lifting seems to be during firing of the fault and accessing data,
  // so i'm trying to do that in the background thread.
  UIImage *i = [UIImage imageWithData:self.imageEntity.data];
  // I now need to notify observers that the image is ready on the main thread
  dispatch_async(dispatch_get_main_queue(), ^{
    [self willChangeValueForKey:@"image"];
    image = i;
    [self didChangeValueForKey:@"image"];
  });
});
Run Code Online (Sandbox Code Playgroud)

该项目使用ARC,我没有得到任何编译器错误或警告,当我运行它有点工作,直到我快速滚动,然后当我声明i时我在线路上得到一个EXC_BAD_ACCESS.

我在这里错过了什么?

diz*_*izy 7

显然,获取CoreData对象不是线程安全的.因此建议使用相同的persistentStoreCoordinator,但使用不同的ObjectContexts.这是我的更新代码,似乎不再崩溃:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  @autoreleasepool {
    // Create a new context
    NSManagedObjectContext *backgroundContext = [[NSManagedObjectContext alloc] init];
    // Use an existing coordinator
    NSPersistentStoreCoordinator *coordinator = [[DataSource sharedDataSource] persistentStoreCoordinator];
    [backgroundContext setPersistentStoreCoordinator:coordinator];
    // Getting objectID does not fire the fault, so we grab it but actually fetch the object
    // on a background context to be thread safe.
    Image *imageEntity = (Image*)[backgroundContext objectWithID:self.imageEntity.objectID];
    image = [UIImage imageWithData:imageEntity.data];
    // Notify observers that the image is ready on the main thread
    dispatch_async(dispatch_get_main_queue(), ^{
      [self willChangeValueForKey:@"image"];
      [self didChangeValueForKey:@"image"];
    });
  }
});
Run Code Online (Sandbox Code Playgroud)