使用主要managedObjectContext中的Object的CoreData和dispatch_async

时间:2013-05-16 18:08:02

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

我需要从后台线程更改一些实体,所以我执行以下操作:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    NSManagedObjectContext *parent = [Default managedObjectContext];
    NSManagedObjectContext *editContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:parent.concurrencyType];
    [editContext setPersistentStoreCoordinator:[Default persistentStoreCoordinator]];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(saveChanges:)
                                                 name:NSManagedObjectContextDidSaveNotification
                                               object:editContext];

    NSFetchRequest *request = [NSFetchRequest new];
    ...
    NSArray *fetchedObjects = [context executeFetchRequest:request error:nil];

    NSError *error;
    [editContext save:&error]
});

它正在工作,但有时它会停止工作,只是从executeFetchRequest:request上的函数退出。它发生在模拟器上。 那么从后台线程更改数据是否正确?

1 个答案:

答案 0 :(得分:1)

是的,您可以将后台线程中的数据更改为核心数据,但作为一个黄金法则“每个线程都应该拥有自己的NSManagedObjectContext实例”并使用相同的persistentStoreCoordinator,因为这样可以避免数据库和其他方面的死锁讨厌的问题。

但我在你的代码中看到了一些问题,我不知道是编辑错误还是真正的错误。

  1. context您正在使用提取请求。
  2. 您应该在saveChanges执行后删除save观察者。 (您不希望被其他更改通知)
  3. 在块中使用self是一种不好的做法(这不是你的情况),因为它可能导致保留周期。您应该使用__block YoirClass *blocksafeSelf = self;
  4. 此外很难在没有错误的情况下知道这可能是什么问题,因此您应该将错误参数传递给fetchRequest并检查是否存在错误。

    还要确保它真的退出该函数,因为在死锁的情况下它看起来就像是退出但实际上它只是停在线上并等待。