我正在使用following tutorial在我的Swift IOS应用程序中实现Core Data。如视频所示,我的持久性管理器是通过单例模式创建的。这是描述它的代码:

import Foundation
import CoreData

class DataLogger {

    private init() {}
    static let shared = DataLogger()
    lazy var context = persistentContainer.viewContext

    private var persistentContainer: NSPersistentContainer = {
        let container = NSPersistentContainer(name: "mycoolcontainer")
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                print("Unresolved error \(error), \(error.userInfo)")
            }
        })
        return container
    }()

    func save () {
        if self.context.hasChanges {
            self.context.perform {
                do {
                    try self.context.save()
                } catch {
                    print("Failure to save context: \(error)")
                }
            }
        }
    }
}

现在,如果使用以下代码创建一个包含约1000个实体元素(MyEntity是Core Data实体对象)的循环,则应用程序将崩溃。
class MySampleClass {

    static func doSomething {
        for i in 0 ..< 1000 {
            let entry = MyEntity(context: DataLogger.shared.context);
            // do random things
        }
        DataLogger.shared.save()
    }
}

它在MyEntity(context:DataLogger.shared.context)上崩溃,并且我无法观察任何日志以了解原因。有时,它将到达save()调用并成功或崩溃,并显示以下一般错误:



我试图在网上四处寻找有关此问题可能的任何提示。我试图通过.performAndWait()使DataLogger中的save()方法同步,但没有成功。我还尝试通过以下代码使用childContexts来执行相同的操作,但没有成功:
let childContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
childContext.parent = context
childContext.hasChanged {
    childContext.save();
}

我怀疑我错误地实现了DataLogger类,但无法观察到实际的问题。它可能与创建对象的数量或线程有关,但我不确定。实现DataLogger类以确保任何其他类都可以使用它并将实体存储到磁盘的正确方法是什么?

最佳答案

我最终阅读了有关核心数据的更多信息,并通过以下方式解决了该问题:

首先,我最终将持久性容器移动到应用程序委托(delegate)中。可以定义如下:

 import UIKit
 import CoreData

 @UIApplicationMain
 class AppDelegate: UIResponder, UIApplicationDelegate {

      ... applicationWillTerminate ....

      // add the core data persistance controller
    lazy var persistentContainer: NSPersistentContainer = {
        let container = NSPersistentContainer(name: "mycoolcontainer")
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                print("Unresolved error \(error), \(error.userInfo)")
            }
        })
        return container;
    }()

    func save() {
        let context = persistentContainer.viewContext;
        if context.hasChanges {
            do {
                try context.save()
            } catch {
                print("Failure to save context: \(error)")
            }
        }
    }

 }

在需要访问上下文的每个 View Controller 中,我将执行以下操作:
import UIKit

class CoolViewController: UIPageViewController, UIPageViewControllerDelegate {

    let appDelegate = UIApplication.shared.delegate as! AppDelegate;

    func storeAndFetchRecords() {
        MySampleClass().doSomething(context: appDelegate.persistentContainer.viewContext);
        appDelegate.save()
    }

}

需要与上下文进行交互的类将按以下方式进行操作:
import CoreData

class MySampleClass {

    func doSomething(context: NSManagedObjectContext) {
        for i in 0 ..< 1000 {
            let entry = MyEntity(context: context);
            // do random things
        }
    }
}

由于这位于主线程上,因此无需运行“performAndWait”。仅当通过以下语法启动了后台上下文时,这才有意义:
appDelegate.persistentContainer.newBackgroundContext()

关于ios - 在Swift 5中配置核心数据持久性,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57699336/

10-11 14:51