如何正确使用 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 的调用包装在其中,这样您就不会遇到任何写入冲突。可以在此处找到更完整的描述: