Search code examples
swiftswiftuiswiftdata

Access Core Data ModelContainer with SwiftData


I have an app that uses CoreData and I want to migrate to SwiftData. After following the Migrate to SwiftData session, I only need to point to my old Core Data file to read the old data and convert it to the new SwiftData format.

My question is how do I do this? Maybe worth mentioning is that my NSPersistentContainer(name: "Model") is different to my app name.


Possible Solution?

According to a Tweet by Donny Wals this is done this way:

By default a SwiftData ModelContainer will create its underlying storage in a file called default.store. If you want to change this so you can use an existing Core Data SQLite file, you can point your container to that file instead:

// point to your old sqlite file
let url = URL.applicationSupportDirectory.appending(path: "Model.sqlite")
let config = ModelConfiguration(url: url)

modelContainer = try ModelContainer(for: [
   Movie.self
], config)

My Tested Code

@main
struct SwiftData_TestApp: App {
    let url = URL.applicationSupportDirectory.appending(path: "Model.sqlite")
    let config = ModelConfiguration(url: url)
    
    let modelContainer = try ModelContainer(for: [
        Item.self
    ], config)

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .modelContainer(modelContainer)
    }
}

The problem here is that I don’t get it to work in the main app struct. When using this the way described in Dive deeper into SwiftData (at 6:58) I only get the error: Cannot use instance member 'url' within property initializer; property initializers run before 'self' is available

PS: There seems to be an issue with this WWDC session method anyway – see here.


Solution

  • As mentioned by Joakim Danielson in the comments, the issue was the wrong initialization:

    @main
    struct SwiftData_TestApp: App {
        let url = URL.applicationSupportDirectory.appending(path: "Model.sqlite")
        let modelContainer: ModelContainer
    
        init() {
            do {
                modelContainer = try ModelContainer(
                    for: [Item.self],
                    configurations: ModelConfiguration(url: url))
            } catch {
                fatalError("Failed to initialize model container.")
            }
        }
    
        var body: some Scene {
            WindowGroup {
                ContentView()
            }
            .modelContainer(modelContainer)
        }
    }
    ``