Forcing NSPersistentContainer change Core Data

痞子三分冷 提交于 2021-02-06 09:13:44

问题


I just added the option for a user to toggle Cloud sync inside my app where I save whether or not the user wants to use iCloud sync in UserDefaults under "useCloudSync". I load my persistentContainer when the app runs with:

class CoreDataManager {
    static let sharedManager = CoreDataManager()
    private init() {}

    lazy var persistentContainer: NSPersistentContainer = {
        var useCloudSync = UserDefaults.standard.bool(forKey: "useCloudSync")

        let containerToUse: NSPersistentContainer?
        if useCloudSync {
           containerToUse = NSPersistentCloudKitContainer(name: "App")
        } else {
            containerToUse = NSPersistentContainer(name: "App")
            let description = containerToUse!.persistentStoreDescriptions.first
            description?.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
      }

        guard let container = containerToUse, let description = container.persistentStoreDescriptions.first else {
            fatalError("Hey Listen! ###\(#function): Failed to retrieve a persistent store description.")
        }
        description.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)

        container.loadPersistentStores(completionHandler: { (storeDescription, error) in

      ...

      return container
   }
}

When a user toggles cloud sync with a UISwitcher, I change the value for "useCloudSyc" in UserDefaults, but the app doesn't use the NSPersistentCloudKitContainer until they force close the app and re-run it again. I would like the container to change right when the user toggles the switch to start loading their data from iCloud.

How can I change to and from a NSPersistentCloudKitContainer when the user toggles "CloudSync"?


回答1:


Here is possible approach

extension UserDefaults { // helper key path for observing
    @objc dynamic var useCloudSync: Bool {
        return bool(forKey: "useCloudSync")
    }
}

class CoreDataManager {
    static let sharedManager = CoreDataManager()

    private var observer: NSKeyValueObservation?
    private init() {
    }

    lazy var persistentContainer: NSPersistentContainer = {
        setupContainer()
    }()

    private func setupContainer() -> NSPersistentContainer {

        if nil == observer {
            // setup observe for defults changed
            observer = UserDefaults.standard.observe(\.useCloudSync) { [weak self] (_, _) in
                try? self?.persistentContainer.viewContext.save() // save anything pending
                if let newContainer = self?.setupContainer() {
                    self?.persistentContainer = newContainer
                }
            }
        }

        let useCloudSync = UserDefaults.standard.bool(forKey: "useCloudSync")

        let containerToUse: NSPersistentContainer?
        if useCloudSync {
            containerToUse = NSPersistentCloudKitContainer(name: "App")
        } else {
            containerToUse = NSPersistentContainer(name: "App")
            let description = containerToUse!.persistentStoreDescriptions.first
            description?.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
        }

        guard let container = containerToUse, let description = container.persistentStoreDescriptions.first else {
            fatalError("Hey Listen! ###\(#function): Failed to retrieve a persistent store description.")
        }
        description.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)

        container.loadPersistentStores { (storeDescription, error) in
            //      ...
        }

        return container
    }
}


来源:https://stackoverflow.com/questions/61025346/forcing-nspersistentcontainer-change-core-data

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!