Toggle iCloud sync during runtime
Asked Answered
K

2

5

I have a SwiftUI App, where the user can buy with in-app purchases some premium features. One of this features is iCloud sync over more devices. I am using CoreData to save users data. My persistent container:

lazy var persistentContainer: NSPersistentCloudKitContainer = {
        let container = NSPersistentCloudKitContainer(name: "store name")
        let description: NSPersistentStoreDescription? = container.persistentStoreDescriptions.first
        let remoteChangeKey: String = "NSPersistentStoreRemoteChangeNotificationOptionKey"
        if(description != nil) {
            description!.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
            description!.setOption(true as NSNumber, forKey: remoteChangeKey)
        }
        
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })
        return container
    }()

My question is how can I toggle on/off cloud sync when the user buy a subscription. I don't want hat the user have to restart the app. I also want that the user can toggle this setting in the in-app settings.

Keri answered 4/2, 2020 at 17:58 Comment(0)
C
4

Declare your variable as a NSPersistentContainer instead of NSPersistentCloudKitContainer. On launch, if the user has cloud sync, load the cloud kit persistent container, otherwise load the non-cloud kit one.

When the switch is toggled, reload the container, following the same rules. To reload the container, I would add the property to a manager object, in which I would add some methods that reload the the container depending on the user's settings.

Cumuliform answered 4/2, 2020 at 18:4 Comment(2)
Something like that? ` lazy var ..... let container = self.iapManager.isPremiumVersion ? NSPersistentCloudKitContainer(name: "store name") : NSPersistentContainer(name: "store name") .... ` But haw can I reload the container?Keri
I have been able to find a solution: #65356220Talca
F
0

Based on the answer given by an engineer from Apple, the right way to do this is to set the cloudKitContainerOptions to nil when you want to disable iCloud sync. However, simply setting it to nil will not work. A new container needs to be created every time user changes their preference

class DataController: ObservableObject {

    private var container: NSPersistentCloudKitContainer!

    init(iCloudSync: Bool) {
        setupContainer(iCloud: iCloudSync)
    }

    private func setupContainer(iCloud: Bool) {
        container = NSPersistentCloudKitContainer(name: "Model_Name")

        guard let description: NSPersistentStoreDescription = container.persistentStoreDescriptions.first else {
            fatalError()
        }

        description.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
        description.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)

        if iCloud == false {
            description.cloudKitContainerOptions = nil
        }

        container.loadPersistentStores { description, error in
            if let error {
                print("Failed to load data \(error.localizedDescription)")
            }
        }
    }

    var iCloudSync: Bool {
        get { container.persistentStoreDescriptions.first!.cloudKitContainerOptions != nil }
        set { setupContainer(iCloud: newValue) }
    }
}

You can either have a singleton of DataController or maintain an object in AppDelegate

Frankiefrankincense answered 24/9, 2023 at 8:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.