如何正确使用 Core Data managedObjectContext 以及保存上下文的正确方法?
How to use Core Data managedObjectContext properly and a proper way to save context?
在我的应用程序中,我有一个特殊的 CoreDataManager class 负责我应用程序中的所有核心数据操作。
CoreDataManager Class 中的第一行如下所示:
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 class 的单例,以及(保存、编辑、 class.
中声明的删除实体)
在我的应用程序中,我还有一个 LocalNotificationManager,当我从 CloudKit
收到更改或删除时,我会在其中对 CoreData
实体执行一些操作一些实体。当我想保存更改时,我正在调用 CoreDataManager.sharedInstance.saveViewContext()
,并且“认为我做错了,因为有时我会出错。
我不是很清楚如何正确调用context并保存,有以下问题:
在我的保存、编辑、删除调用中,我应该use/savemainContext还是privateContext?
收到通知后,我应该use/savemainContext还是privateContext?
什么时候应该从主线程保存 viewContext,什么时候使用私有托管对象上下文?我应该使用 .MainQueueConcurrencyType 还是可以避免?
我应该在我的 CoreDataManager class 中声明一个 privateObjectContext 变量吗?哪个是正确的方法?
我看到可以用这种方式声明私有上下文,但是我可以在我的 CoreDataManager class 中实现它吗?我什么时候应该调用它而不是 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)")
}
})
谁能说清楚在不同情况下保存上下文的正确用法吗?
Swift4,Xcode9.
您有两个选择:
简单的方法
只能从主线程读取和写入 viewContext。这会起作用,但如果您有大量数据同时读取或写入,它会阻塞您的 UI。如果您的应用程序在核心数据中存储了少量内容,这将可以正常工作,并且是迄今为止最简单的选择。
复杂的方式
使用 viewContext 进行所有读取,但切勿写入。只能从主线程访问 viewContext。使用 persistentContainer.performBackgroundTask
完成所有写作,并使用传递到块中的上下文。不要在此块内使用任何其他 managedObjects。如果您需要然后传递一个 objectId 并在块内进行提取。不要将任何对象传递到这些块之外。如果您发现需要,请使用 objectId。您还需要创建一个 operationQueue 并将所有对 performBackgroundTask
的调用包装在其中,这样您就不会遇到任何写入冲突。可以在此处找到更完整的描述:
在我的应用程序中,我有一个特殊的 CoreDataManager class 负责我应用程序中的所有核心数据操作。
CoreDataManager Class 中的第一行如下所示:
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 class 的单例,以及(保存、编辑、 class.
中声明的删除实体)在我的应用程序中,我还有一个 LocalNotificationManager,当我从 CloudKit
收到更改或删除时,我会在其中对 CoreData
实体执行一些操作一些实体。当我想保存更改时,我正在调用 CoreDataManager.sharedInstance.saveViewContext()
,并且“认为我做错了,因为有时我会出错。
我不是很清楚如何正确调用context并保存,有以下问题:
在我的保存、编辑、删除调用中,我应该use/savemainContext还是privateContext?
收到通知后,我应该use/savemainContext还是privateContext?
什么时候应该从主线程保存 viewContext,什么时候使用私有托管对象上下文?我应该使用 .MainQueueConcurrencyType 还是可以避免?
我应该在我的 CoreDataManager class 中声明一个 privateObjectContext 变量吗?哪个是正确的方法?
我看到可以用这种方式声明私有上下文,但是我可以在我的 CoreDataManager class 中实现它吗?我什么时候应该调用它而不是 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)")
}
})
谁能说清楚在不同情况下保存上下文的正确用法吗?
Swift4,Xcode9.
您有两个选择:
简单的方法
只能从主线程读取和写入 viewContext。这会起作用,但如果您有大量数据同时读取或写入,它会阻塞您的 UI。如果您的应用程序在核心数据中存储了少量内容,这将可以正常工作,并且是迄今为止最简单的选择。
复杂的方式
使用 viewContext 进行所有读取,但切勿写入。只能从主线程访问 viewContext。使用 persistentContainer.performBackgroundTask
完成所有写作,并使用传递到块中的上下文。不要在此块内使用任何其他 managedObjects。如果您需要然后传递一个 objectId 并在块内进行提取。不要将任何对象传递到这些块之外。如果您发现需要,请使用 objectId。您还需要创建一个 operationQueue 并将所有对 performBackgroundTask
的调用包装在其中,这样您就不会遇到任何写入冲突。可以在此处找到更完整的描述: