luegm.dev
luegm.dev

Reputation: 161

toggle between local and iCloud CoreData store

this is my PersistenceController:

import CoreData

struct PersistenceController {
    
    static let shared = PersistenceController()
    let container: NSPersistentContainer
    
    init() {
        container = NSPersistentCloudKitContainer(name: "LogModel")
        container.loadPersistentStores {(descr, error) in
            if let error = error as NSError? {
                fatalError("Container load failed: \(error)")
            }
        }
        
        container.viewContext.automaticallyMergesChangesFromParent = true
        container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
    }
}

here I inject the container.

import SwiftUI

@main
struct MyApp: App {
    var persistanceContainer = PersistenceController()

    var body: some Scene {        
        WindowGroup {
            ContentView()
                .environmentObject(CoreBluetoothViewModel())
                .environment(\.managedObjectContext, persistanceContainer.container.viewContext)
        }
    }
}

I want to use this View to toggle between Cloud and Local store.

struct iCloudSyncView: View {
    @Environment(\.managedObjectContext) private var viewContext
    @State private var cloudEnabled = true

    var body: some View {
        Toggle("iCloud sync", isOn: $cloudEnabled)
    }
}

I know that i have to use the NSPersistentCloudKitContainerfor the cloud and the NSPersistentCloudKitContainerfor the local store.

Also I found this article: CoreData+CloudKit | On/off iCloud sync toggle

But I just can't get it to work :/
Can someone please tell me how I have to implement this?


I would add it like this:

struct PersistenceController {
    
    let iCloud = UserDefaults.standard.bool(forKey: "iCloud")
    
    static let shared = PersistenceController()
    var container: NSPersistentContainer
    
    init() {
        if iCloud {
            container = NSPersistentCloudKitContainer(name: "LogModel")
        } else {
            container = NSPersistentContainer(name: "LogModel")
        }
        container.loadPersistentStores {(descr, error) in
            if let error = error as NSError? {
                fatalError("Container load failed: \(error)")
            }
        }
        
        container.viewContext.automaticallyMergesChangesFromParent = true
        container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
    }
}

But I don't know how to load the new container when toggle is changed.

Toggle("iCloud sync", isOn: $cloudEnabled)
      .onChange(of: cloudEnabled) { value in
           saveContext()
           UserDefaults.standard.set(value, forKey: "iCloud")
           //get new container
      }

Upvotes: 1

Views: 363

Answers (1)

malhal
malhal

Reputation: 30746

There are 2 ways

  1. add local and cloud configurations to the model editor and set them on the store description and assign different entities to each config.

  2. Use affectedStores for fetching and assign(to:) when creating new objects to manually select the store.

1 is best.

Upvotes: 0

Related Questions