Is there a way to use Core Data/CloudKit to store and move data with Swift UI in Xcode 12?

It seems that AppDelegate and SceneDelegate are no longer needed in Swift UI in Xcode 12. I'm having trouble figuring out how to build an iCloud/Core Data enabled application with Swift UI. Is there a video/tutorial/guide on implementing Core Data or Cloudkit with the new Swift UI frameworks yet?

Accepted Reply

You can create your custom PersistentCloudKitContainer Class.

One thing I was still struggling with was to apply the Merge Policies. I couldn't figure out how this works. Thats why they are commented out in my code below.

Code Block
import SwiftUI
import CoreData
@main
struct TestApp: App {
    let context = PersistentCloudKitContainer.persistentContainer.viewContext
    //context.automaticallyMergesChangesFromParent = true
    //context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
    var body: some Scene {
        WindowGroup {
            ContentView().environment(\.managedObjectContext, context)
        }
    }
}


And my Custom Class

Code Block
import CoreData
public class PersistentCloudKitContainer {
    // MARK: - Define Constants / Variables
    public static var context: NSManagedObjectContext {
        return persistentContainer.viewContext
    }
    // MARK: - Initializer
    private init() {}
    // MARK: - Core Data stack
    public static var persistentContainer: NSPersistentContainer = {
        let container = NSPersistentContainer(name: "Model")
        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
    public static 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)")
            }
        }
    }
}


Replies

You can create your custom PersistentCloudKitContainer Class.

One thing I was still struggling with was to apply the Merge Policies. I couldn't figure out how this works. Thats why they are commented out in my code below.

Code Block
import SwiftUI
import CoreData
@main
struct TestApp: App {
    let context = PersistentCloudKitContainer.persistentContainer.viewContext
    //context.automaticallyMergesChangesFromParent = true
    //context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
    var body: some Scene {
        WindowGroup {
            ContentView().environment(\.managedObjectContext, context)
        }
    }
}


And my Custom Class

Code Block
import CoreData
public class PersistentCloudKitContainer {
    // MARK: - Define Constants / Variables
    public static var context: NSManagedObjectContext {
        return persistentContainer.viewContext
    }
    // MARK: - Initializer
    private init() {}
    // MARK: - Core Data stack
    public static var persistentContainer: NSPersistentContainer = {
        let container = NSPersistentContainer(name: "Model")
        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
    public static 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)")
            }
        }
    }
}


You can set the merge policy when creating the container; between line 20 and 21 in your example:
Code Block swift
container.viewContext.automaticallyMergesChangesFromParent = true
container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy


When following this, i keep getting the error, cannot find type "MyHumidor" in scope.

My App.swift and the CoreData.swift files below (created the coredata.swift to hold the public class)

Code Block
import SwiftUI
@main
struct My_HumidorApp: App {
let context = PersistentCloudKitContainer.persistentContainer.viewContext
var body: some Scene {
WindowGroup {
ContentView().environment(\.managedObjectContext, context)
}
}
}


Code Block
//
// CoreData.swift
// My Humidor
//
// Created by Adam Hewitt on 28/06/2020.
//
import Foundation
import CoreData
public class PersistentCloudKitContainer {
// MARK: - Define Constants / Variables
public static var context: NSManagedObjectContext {
return persistentContainer.viewContext
}
// MARK: - Initializer
private init() {}
// MARK: - Core Data stack
public static var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "My_Humidor")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
container.viewContext.automaticallyMergesChangesFromParent = true
container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
return container
}()
// MARK: - Core Data Saving support
public static 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)")
}
}
}
}


This is the start of my content view:

Code Block
import SwiftUI
struct ContentView: View {
@Environment(\.managedObjectContext) var moc
@FetchRequest(entitiy: MyHumidors.entity(), sortDescriptors:[]) var humidor: FetchRequest<MyHumidors>


Any ideas what is causing this from a code perspective?
An important warning, sometimes Xcode 12 doesn't recognize the entity, to solve this, close and reopen the Xcode and everything will work normally.
There's a longer thread about that here. There you'll find a few posts with possibly helpful examples.