在我的应用中,我有一个特殊的 CoreDataManager 类,负责我的应用中的所有Core Data操作。
CoreDataManager 类中的第一行如下所示:
static var sharedInstance: CoreDataManager = { // or private static var
let instance = CoreDataManager()
return instance
}()
// Init
override init() {
self.persistentContainer = NSPersistentContainer.init(name: "AppName")
self.persistentContainer.loadPersistentStores { (storeDescription, error) in
if let error = error as NSError? {
fatalError("CoreDataManager: init, loadPersistentStores error: \(error), \(error.userInfo)")
} else {
print("CoreDataManager: init() func finished with Success!")
}
}
self.persistentContainer.viewContext.undoManager = nil
self.persistentContainer.viewContext.shouldDeleteInaccessibleFaults = true
self.persistentContainer.viewContext.automaticallyMergesChangesFromParent = true
}
let persistentContainer: NSPersistentContainer
var viewContext: NSManagedObjectContext? {
return self.persistentContainer.viewContext
}
func saveViewContext() {
let context = self.viewContext
if self.viewContext != nil {
if context!.hasChanges {
do {
try context!.save()
} catch {
let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
}
}
}
当我需要在我的应用程序中保存,编辑或删除核心数据实体时,我会调用 CoreDataManager 类的单例,以及在此类中声明的(保存,编辑,删除实体)方法。
在我的应用中,我还有 LocalNotificationManager ,当我从CoreData
收到更改或删除某些实体时,我会在CloudKit
个实体中执行一些操作。当我想保存更改时,我正在调用CoreDataManager.sharedInstance.saveViewContext()
,并且“认为我做错了,因为有时我会遇到错误。
我不清楚如何正确调用上下文并保存它,并提出以下问题:
在我的保存,编辑,删除通话中,我应该使用/保存 mainContext 还是 privateContext ?
收到通知后,我应该使用/保存 mainContext 还是 privateContext ?
何时应该从主线程保存viewContext,何时使用私有托管对象上下文?我应该使用 .MainQueueConcurrencyType 还是我可以避免它?
我应该在 CoreDataManager 类中声明 privateObjectContext 变量,这是正确的方法吗?
我已经看到私有上下文可以通过这种方式声明,但我可以在 CoreDataManager 类中实现它,何时应该调用它而不是saveViewContext()
。
let moc = NSManagedObjectContext(concurrencyType:.MainQueueConcurrencyType)
let privateMOC = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
privateMOC.parentContext = moc
privateMOC.performBlock({
do {
try privateMOC.save()
} catch {
fatalError("Failure to save context: \(error)")
}
})
任何人都可以清楚地解释在不同情况下保存上下文的正确用法吗?
Swift 4,Xcode 9。
答案 0 :(得分:1)
您有两种选择:
仅对viewContext进行读写,并且仅从主线程进行读写。这将有效但如果您有大量数据,您一次正在阅读或写入,它将阻止您的用户界面。如果你有一个应用程序,核心数据中存储了少量的东西,这将工作正常,是迄今为止最简单的选项。
使用viewContext完成所有阅读,但绝不写入。仅从主线程访问viewContext。使用persistentContainer.performBackgroundTask
完成所有写作并使用传递给块的上下文。不要在此块中使用任何其他managedObject。如果你需要传递一个objectId并在块内进行一次获取。不要在这些街区之外传递任何物体。如果您发现需要,则使用objectId。您还需要创建一个operationQueue并将所有调用包装到其中performBackgroundTask
,这样您就不会发生任何写入冲突。