如何在正确的队列上初始化ManagedObjectContext?

时间:2017-02-01 19:49:28

标签: ios multithreading core-data concurrency

非常需要一个建议,目前用完了想法。我堆栈与核心数据并发相关的问题,调试我使用 - " com.apple.CoreData.ConcurrencyDebug"我有什么:

堆栈:

线程3队列:coredata(串行)

  

0 + [NSManagedObjectContext Multithreading_Violation_AllThatIsLeftToUsIsHonor ]:   CoreData`- [NSManagedObjectContext executeFetchRequest:error:]:

     

1 - [NSManagedObjectContext executeFetchRequest:error:]:

     

2 NSManagedObjectContext.fetch(__ ObjC.NSFetchRequest)抛出 - > Swift.Array:

     

3 AppDelegate。(fetchRequest NSFetchRequest) - > [A])。(关闭#1)

我从这里进入AppDelegate :: fetchRequest:

let messageRequest: NSFetchRequest<ZMessage> = ZMessage.fetchRequest();
messageRequest.sortDescriptors = [NSSortDescriptor(key: "id", ascending: false)];
let messageArray: Array<ZMessage> = self.fetchRequest(messageRequest);

我在串行队列上执行所有coredata东西(self.queueContainer)。

public func fetchRequest<T>(_ request: NSFetchRequest<T>) -> Array<T>
{
    var retval: Array<T> = Array<T>();      
    self.queueContainer.sync {
        do {
            retval = try self.persistentContainer.viewContext.fetch(request);
        } catch {
            let nserror = error as NSError;
            fatalError("[CoreData] Unresolved fetch error \(nserror), \(nserror.userInfo)");
        }
    }
    return retval;
}

这是我觉得有用的。

  

如果您不希望使用CoreData的应用崩溃(或)破坏数据库,则必须遵循以下规则:

     

NSManagedObjectContext只能用于与之关联的队列。

     

如果使用.PrivateQueueConcurrencyType初始化,则会创建与该对象关联的专用内部队列。可以通过实例方法访问此队列.performBlockAndWait(用于同步操作)和.performBlock(用于异步操作)

     

如果使用.MainQueueConcurrencyType初始化,则该对象只能在主队列上使用。这里也可以使用相同的实例方法(performBlock和performBlockAndQueue)。   NSManagedObject不应该在初始化它的线程之外使用

现在我正在挖掘,但老实说,不能确定我的托管对象上下文(MOC)与正确的队列相关联。

来自手册:

  

......这样做的结果是上下文假定默认所有者是分配它的线程或队列 - 这由调用其init方法的线程确定。

在AppDelegate中我不直接使用MOC,而不是我实例化拥有此MOC的NSPersistentContainer。以防我在同一个串行队列中执行此操作。

public lazy var persistentContainer: NSPersistentContainer =
{
    self.queueContainer.sync {
        let container = NSPersistentContainer(name: "Joker")
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })

        return container
    }
}()

提前致谢。

1 个答案:

答案 0 :(得分:1)

我不是Swift程序员,但什么是queueContainer?

你应该不自己做线程,你应该使用你在引文中写的NSManagedObjectContext block methods

  

相同的实例方法(performBlock和performBlockAndQueue)可以   也可以在这里使用。

managedObjectContext.performBlock {

无论您使用的是哪个managedObjectContext,都应该使用该上下文块方法并在块方法中执行您的操作。

Look at the documentation这里有关于如何正确执行此操作的示例。

还要避免崩溃和线程错误:

  

NSManagedObject实例不打算在它们之间传递   队列。这样做会导致数据损坏和终止   申请。当需要交出托管对象时   从一个队列引用另一个队列,必须完成   NSManagedObjectID实例。

     

通过调用来检索托管对象的托管对象ID   NSManagedObject实例上的objectID方法。