从后台线程使用核心数据托管上下文......你如何正确地做到这一点?
Using CoreData managedContext from background thread...how do you do it correctly?
我打开了 CoreData 并发调试器,我在每个地方都断言。我想不通。
我在后台线程上创建了我认为是上下文的内容。请看一下我的 CoreData Stack:
import Foundation
import CoreData
class CoreDataManager {
lazy var managedContext: NSManagedObjectContext = {
return self.storeContainer.viewContext
}()
lazy var backgroundContext: NSManagedObjectContext = {
return self.storeContainer.newBackgroundContext()
}()
lazy var privateMOC: NSManagedObjectContext = {
let pMOC = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
pMOC.parent = self.storeContainer.viewContext
return pMOC
}()
private lazy var storeContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "XXXX")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
print("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
func saveContext () {
guard managedContext.hasChanges else { return }
do {
try managedContext.save()
} catch let error as NSError {
print("Unresolved error \(error), \(error.userInfo)")
}
self.reset()
}
func reset() {
managedContext.reset()
}
}
然后我尝试从存储库类型中的后台线程执行任务 class:
func deleteAllData() {
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Pairing")
let pairings = (try? self.coreDataManager.privateMOC.fetch(fetchRequest)) as! [Pairing_ManagedObject]. // I GET THE ASSERT HERE
for pairing in pairings {
self.coreDataManager.privateMOC.delete(pairing)
}
self.coreDataManager.saveContext()
}
我该怎么做才能不正确地获取核心数据并发断言?请帮忙
您正在创建一个具有专用队列并发的新托管对象上下文,但这不足以避免并发问题。 Core Data 的政策是您必须 使用performBlock
或performBlockAndWait
来您所做的一切使用该上下文。在您的代码中,这意味着必须使用其中一个函数完成 delete
和 save
调用。
还有第二个问题。您正在使用 saveContext
函数来保存更改。但这不会保存对 private-queue 上下文的更改。它保存在其他一些名为 managedContext
的上下文中。在一个上下文中保存不会自动保存其他上下文。如果您想对私有队列上下文进行更改并保存这些更改,则需要在某个时候保存该上下文。
我打开了 CoreData 并发调试器,我在每个地方都断言。我想不通。
我在后台线程上创建了我认为是上下文的内容。请看一下我的 CoreData Stack:
import Foundation
import CoreData
class CoreDataManager {
lazy var managedContext: NSManagedObjectContext = {
return self.storeContainer.viewContext
}()
lazy var backgroundContext: NSManagedObjectContext = {
return self.storeContainer.newBackgroundContext()
}()
lazy var privateMOC: NSManagedObjectContext = {
let pMOC = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
pMOC.parent = self.storeContainer.viewContext
return pMOC
}()
private lazy var storeContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "XXXX")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
print("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
func saveContext () {
guard managedContext.hasChanges else { return }
do {
try managedContext.save()
} catch let error as NSError {
print("Unresolved error \(error), \(error.userInfo)")
}
self.reset()
}
func reset() {
managedContext.reset()
}
}
然后我尝试从存储库类型中的后台线程执行任务 class:
func deleteAllData() {
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Pairing")
let pairings = (try? self.coreDataManager.privateMOC.fetch(fetchRequest)) as! [Pairing_ManagedObject]. // I GET THE ASSERT HERE
for pairing in pairings {
self.coreDataManager.privateMOC.delete(pairing)
}
self.coreDataManager.saveContext()
}
我该怎么做才能不正确地获取核心数据并发断言?请帮忙
您正在创建一个具有专用队列并发的新托管对象上下文,但这不足以避免并发问题。 Core Data 的政策是您必须 使用performBlock
或performBlockAndWait
来您所做的一切使用该上下文。在您的代码中,这意味着必须使用其中一个函数完成 delete
和 save
调用。
还有第二个问题。您正在使用 saveContext
函数来保存更改。但这不会保存对 private-queue 上下文的更改。它保存在其他一些名为 managedContext
的上下文中。在一个上下文中保存不会自动保存其他上下文。如果您想对私有队列上下文进行更改并保存这些更改,则需要在某个时候保存该上下文。