如何在 AppDelegate 中初始化 Core Data 的持久化容器并在整个应用程序中使用它?

Posted

技术标签:

【中文标题】如何在 AppDelegate 中初始化 Core Data 的持久化容器并在整个应用程序中使用它?【英文标题】:How do I initialize the Core Data's persistent container in AppDelegate and use it throughout the app? 【发布时间】:2020-08-02 16:17:45 【问题描述】:

我正在尝试在整个应用程序的多个视图控制器中使用 NSPersistentContainer 来获取 Core Data。

最初,我在单个视图控制器中设置了容器,效果很好:

第一个视图控制器

var container: NSPersistentContainer!

container = NSPersistentContainer(name: "MyCoreData")
container.loadPersistentStores  storeDescription, error in
    self.container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy

    if let error = error 
        print("Unresolved error \(error.localizedDescription)")
    

但是,我根据苹果的documentation将此代码迁移到AppDelegate

AppDelegate

class AppDelegate: UIResponder, UIApplicationDelegate 
    var window: UIWindow?
    lazy var persistentContainer: NSPersistentContainer = 
        let container = NSPersistentContainer(name: "MyCoreData")
        container.loadPersistentStores  description, error in
            container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
            if let error = error 
                fatalError("Unable to load persistent stores: \(error)")
            
        
        return container
    ()

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool 
        if let firstVC = window?.rootViewController as? FirstViewController 
            firstVC.container = persistentContainer
        
        
        if let secondVC = window?.rootViewController as? SecondViewController 
            secondVC.container = persistentContainer
        
        
        return true
    

我的每个视图控制器现在都有一个名为containerNSPersistentContainer 类型的变量。但是,当我加载视图控制器时,出现以下错误:

在隐式展开可选值时意外发现 nil

此错误指向container.viewContext 所在的位置。更具体地说:

fetchedResultsController = NSFetchedResultsController(fetchRequest: request, managedObjectContext: container.viewContext, sectionNameKeyPath: "title", cacheName: nil)

我不确定我是否收到来自 rootViewController 的错误,因为我没有一个根视图控制器,因为我正在使用标签栏控制器。

【问题讨论】:

你应该初始化persistentContainer一次(AppDelegate很好)并在你的viewControllers中传递一个对managedObjectContext的引用。使用 managedObjectContext 访问您的实体、编辑、删除和保存它们。 【参考方案1】:

我的建议是UIViewController 扩展中的 lazy instantiated 计算属性,实际上您只需要托管对象上下文。

extension UIViewController 

    var context : NSManagedObjectContext 
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        return appDelegate.persistentContainer.viewContext
    

您还可以添加save 函数。

【讨论】:

我是否应该不初始化持久化容器let container = NSPersistentContainer(name: "MyCoreData"),而只使用context?如何在没有容器的情况下加载持久存储,就像使用 container.loadPersistentStores 一样?我应该把你的代码放在AppDelegate.swift 中吗? 使用你的 AppDelegate 版本和这个扩展。该属性被初始化一次,您可以在UIViewController 的所有子类中使用它。您可以将代码放入AppDelegate 文件或额外文件Extensions.swift 我收到了错误Extensions must not contain stored properties 对不起,我的错,它必须是一个计算属性,请参阅编辑。

以上是关于如何在 AppDelegate 中初始化 Core Data 的持久化容器并在整个应用程序中使用它?的主要内容,如果未能解决你的问题,请参考以下文章

从AppDelegate中访问NavigationController指向的初始视图

iOS 如何在 AppDelegate 中以编程方式设置侧边栏菜单?

在 Core Data 中从 AppDelegate 执行回滚功能时需要访问 ManagedObjectContext 的同一实例

导入 AppDelegate

Singleton 类 DataLoader - 在 AppDelegate 中从 Core Data 设置值,但无法访问其他类中的 DataLoader 变量

无法在 AppDelegate 中初始化委托,但在类方法中它可以工作