Che*_*eng 5 core-data ios swift
我想开始学习使用NSAsynchronousFetchRequest参考https://www.marcosantadev.com/coredata_crud_concurrency_swift_2/
我有最简单的用例NSAsynchronousFetchRequest
// Call from UI main thread
func X() {
let fetchRequest = NSFetchRequest<NSPlainNote>(entityName: "NSPlainNote")
let asynchronousFetchRequest = NSAsynchronousFetchRequest(fetchRequest: fetchRequest) { asynchronousFetchResult in
guard let result = asynchronousFetchResult.finalResult as? [NSPlainNote] else { return }
}
let coreDataStack = CoreDataStack.INSTANCE
// backgroundContext created via persistentContainer.newBackgroundContext()
let backgroundContext = coreDataStack.backgroundContext
backgroundContext.perform {
do {
try backgroundContext.execute(asynchronousFetchRequest)
} catch let error {
backgroundContext.rollback()
error_log(error)
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是,运行上面的代码会出现以下错误
CoreData`+[NSManagedObjectContext Multithreading_Violation_AllThatIsLeftToUsIsHonor ]:
如果我修改代码NSFetchRequest直接使用.
// Call from UI main thread
func X() {
let fetchRequest = NSFetchRequest<NSPlainNote>(entityName: "NSPlainNote")
let coreDataStack = CoreDataStack.INSTANCE
// backgroundContext created via persistentContainer.newBackgroundContext()
let backgroundContext = coreDataStack.backgroundContext
backgroundContext.perform {
do {
let nsPlainNotes = try fetchRequest.execute()
} catch let error {
backgroundContext.rollback()
error_log(error)
}
}
}
Run Code Online (Sandbox Code Playgroud)
事情运作良好。我想知道我的NSAsynchronousFetchRequest代码版本有什么问题吗?
这是我的CoreDataStack.swift,仅供参考。
import CoreData
class CoreDataStack {
static let INSTANCE = CoreDataStack()
private init() {
}
private(set) lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "wenote")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
// This is a serious fatal error. We will just simply terminate the app, rather than using error_log.
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
// So that when backgroundContext write to persistent store, container.viewContext will retrieve update from
// persistent store.
container.viewContext.automaticallyMergesChangesFromParent = true
// TODO: Not sure these are required...
//
//container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
//container.viewContext.undoManager = nil
//container.viewContext.shouldDeleteInaccessibleFaults = true
return container
}()
private(set) lazy var backgroundContext: NSManagedObjectContext = {
let backgroundContext = persistentContainer.newBackgroundContext()
// Similar behavior as Android's Room OnConflictStrategy.REPLACE
backgroundContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
// TODO: Not sure these are required...
//backgroundContext.undoManager = nil
return backgroundContext
}()
}
Run Code Online (Sandbox Code Playgroud)
请注意,在NSAsynchronousFetchRequest示例中,即使backgroundContext.perform没有使用。
// Call from UI main thread
func X() {
let fetchRequest = NSFetchRequest<NSPlainNote>(entityName: "NSPlainNote")
let asynchronousFetchRequest = NSAsynchronousFetchRequest(fetchRequest: fetchRequest) { asynchronousFetchResult in
guard let result = asynchronousFetchResult.finalResult as? [NSPlainNote] else { return }
}
let coreDataStack = CoreDataStack.INSTANCE
// backgroundContext created via persistentContainer.newBackgroundContext()
let backgroundContext = coreDataStack.backgroundContext
do {
try backgroundContext.execute(asynchronousFetchRequest)
} catch let error {
backgroundContext.rollback()
error_log(error)
}
}
Run Code Online (Sandbox Code Playgroud)
同样的致命错误仍然发生。
请注意,只有通过使用启动时传递的参数编辑模式才会触发此致命错误
-com.apple.CoreData.ConcurrencyDebug 1
Run Code Online (Sandbox Code Playgroud)
我什至尝试从https://github.com/abhishekbedi1432/Core-Data-Asynchronous-Fetching/tree/master执行一些使用NSAsynchronousFetchRequest.
如果我不启用-com.apple.CoreData.ConcurrencyDebug 1,来自 github 的示例项目能够毫无问题地执行异步获取。然而,一旦-com.apple.CoreData.ConcurrencyDebug 1启用,它也会遇到同样的致命错误。
小智 0
您必须为当前 Core Data 容器创建一个新上下文,无论是子上下文还是根父上下文,如下所示:
let backgroundContext = persistentContainer.newBackgroundContext()
backgroundContext.parent = persistentContainer.viewContext
Run Code Online (Sandbox Code Playgroud)
使用多个上下文的详尽解释在这里。
| 归档时间: |
|
| 查看次数: |
571 次 |
| 最近记录: |