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

时间:2012-02-23 06:15:40

标签: iphone objective-c core-data automatic-ref-counting grand-central-dispatch

我在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"];
  });
});

该项目使用ARC,我没有收到任何编译器错误或警告,当我运行它时,它有效,直到我快速滚动,然后当我声明i时,我在行上得到一个EXC_BAD_ACCESS。 / p>

我在这里缺少什么?

3 个答案:

答案 0 :(得分:7)

显然正在抓取CoreData objects is not thread safe。因此建议使用相同的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"];
    });
  }
});

答案 1 :(得分:1)

Dizy,还要记住在代码中创建的Image对象:

UIImage *i = [UIImage imageWithData:self.imageEntity.data];

设置为自动释放。 dispatch_async方法在主队列上运行,因此在主线程运行调度块时,可能会释放为映像分配的内存。

答案 2 :(得分:0)

CoreData不是线程安全的,您必须管理上下文以避免崩溃。 如果您计划大量使用大量并发进程来更新Core Data中的数据,我建议您查看MagicalRecord,这是一个受Active Record of Rails启发并且处理所有这些方面的惊人模式。非常聪明的方式。