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 this post.

Answered by CryptoKoa in 756704022

This worked:

@main
struct SwiftDataFlashCardSample: App {
   let container: ModelContainer
   
   init() {
      let schema = Schema([Card.self])
      let config = ModelConfiguration(schema: schema, cloudKitContainerIdentifier: "iCloud.org.your.name")
      var contain: ModelContainer? = nil
      do {
         contain = try ModelContainer(for: schema, config)
      } catch {
         print("couldn't create ModelContainer()")
      }
      self.container = contain!
   }
   var body: some Scene {
      WindowGroup {
         ContentView()
      }
      .modelContainer(container)
   }
}

and, as normal, add Capabilities iCloud.cloudKit and BackgroundModes.Remote notifications.

Accepted Answer

This worked:

@main
struct SwiftDataFlashCardSample: App {
   let container: ModelContainer
   
   init() {
      let schema = Schema([Card.self])
      let config = ModelConfiguration(schema: schema, cloudKitContainerIdentifier: "iCloud.org.your.name")
      var contain: ModelContainer? = nil
      do {
         contain = try ModelContainer(for: schema, config)
      } catch {
         print("couldn't create ModelContainer()")
      }
      self.container = contain!
   }
   var body: some Scene {
      WindowGroup {
         ContentView()
      }
      .modelContainer(container)
   }
}

and, as normal, add Capabilities iCloud.cloudKit and BackgroundModes.Remote notifications.

After tons of experimenting (and help from Stack Overflow) I found the solution a few months ago.

This basically matches CryptoKoa’s answer above, so I’m accepting theirs. Just wanted to provide the slightly different code I’ve used regarding the different naming of the old Core Data model.

@main
struct MyApp: App {
    let container: ModelContainer
    
    init() {
        // Legacy placement of the Core Data file.
        let dataUrl = URL.applicationSupportDirectory.appending(path: "Model.sqlite")
        
        do {
            // Create SwiftData container with migration and custom URL pointing to legacy Core Data file.
            container = try ModelContainer(
                for: Foo.self, Bar.self,
                migrationPlan: AppMigrationPlan.self,
                configurations: ModelConfiguration(url: dataUrl))
        } catch {
            fatalError("Failed to initialize model container.")
        }
    }

    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .modelContainer(container)
    }
}
Access Core Data ModelContainer with SwiftData
 
 
Q