非常需要一个建议,目前用完了想法。我堆栈与核心数据并发相关的问题,调试我使用 - " 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
}
}()
提前致谢。
答案 0 :(得分:1)
我不是Swift程序员,但什么是queueContainer?
你应该不自己做线程,你应该使用你在引文中写的NSManagedObjectContext block methods:
相同的实例方法(performBlock和performBlockAndQueue)可以 也可以在这里使用。
managedObjectContext.performBlock {
无论您使用的是哪个managedObjectContext,都应该使用该上下文块方法并在块方法中执行您的操作。
Look at the documentation这里有关于如何正确执行此操作的示例。
还要避免崩溃和线程错误:
NSManagedObject实例不打算在它们之间传递 队列。这样做会导致数据损坏和终止 申请。当需要交出托管对象时 从一个队列引用另一个队列,必须完成 NSManagedObjectID实例。
通过调用来检索托管对象的托管对象ID NSManagedObject实例上的objectID方法。