更改加载的 NSPersistentContainer

Ada*_*aya 1 core-data ios swift

我创建了一个单例类来管理我的核心数据:

class CoreDataManager {
static let sharedManager = CoreDataManager()

private init() {}

lazy var persistentContainer: NSPersistentContainer = {
    let container = NSPersistentContainer(name: "MyContainer")
    if Globals.profileNumber != 0 {
        let alternateURL = NSPersistentContainer.defaultDirectoryURL()
        let storeURL = alternateURL.appendingPathComponent("\(Globals.profileNumber)MyContainer.sqlite")
        let storeDescription = NSPersistentStoreDescription(url: storeURL)
        container.persistentStoreDescriptions = [storeDescription]
    }
    container.loadPersistentStores(completionHandler: { (storeDescription, error) in
        if let error = error as NSError? {
            fatalError("Unresolved error \(error), \(error.userInfo)")
        }
    })
    return container
}()

// MARK: - Core Data Saving support

func saveContext () {
    let context = persistentContainer.viewContext
    if context.hasChanges {
        do {
            try context.save()
        } catch {
            let nserror = error as NSError
            fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
        }
    }
}
}
Run Code Online (Sandbox Code Playgroud)

但是persistentContainer,稍后在应用程序中,我将如何更改指向的商店?

例如,用户加载应用程序,登录并加载默认的 sqlite 文件。然后用户切换到另一个用户帐户,该帐户应该“关闭”当前数据库,persistentContainer然后需要加载不同的存储?

小智 5

正如 klaudas 提供的链接中所述,拥有一个实体与用户有关系的堆栈是一个不错的选择。

如果你想拥有单独的商店,你可以尝试这样的事情:

class CoreDataManager {
    // The rest of your class...

    private(set) var persistentContainer: NSPersistentContainer?

    func setupNewPersistentContainer(completionHandler: @escaping (_ success: Bool) -> Void) {
        let container = NSPersistentContainer(name: "MyContainer")
        // You should also handle the case where profileNumber == 0 and your store URL can't be constructed.
        if Globals.profileNumber != 0 {
            let alternateURL = NSPersistentContainer.defaultDirectoryURL()
            let storeURL = alternateURL.appendingPathComponent("\(Globals.profileNumber)MyContainer.sqlite")
            let storeDescription = NSPersistentStoreDescription(url: storeURL)
            container.persistentStoreDescriptions = [storeDescription]
        }

        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                // Handle the error.
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }

            let success: Bool = error == nil
            completionHandler(success)
        })

        persistentContainer = container
    }

    // The rest of your class...
}
Run Code Online (Sandbox Code Playgroud)

基本上,您将容器设置逻辑放在一个函数中,您在第一次初始化堆栈时调用该函数,然后在切换帐户时调用该函数。您可以调整该类以使persistentContainer 不可选,或者添加一个标志来跟踪存储是否已成功加载。

不过有几点需要注意:

  1. 使用这种方法,您还需要刷新保存在内存中的所有获取的结果控制器和托管对象(因为它们的持久存储不再可访问)。最简单的方法是在切换时重置整个 UI。

  2. 设置新容器时,请等待完成处理程序,然后再继续帐户切换流程。

  3. 如果您有对托管对象的任何引用,您可以通过检查来查看它们在上下文中是否有效object.managedObjectContext?.persistentStoreCoordinator == context.persistentStoreCoordinator