SwiftData, pre-seed database

I started developing a new app, and it's been an exciting journey so far. Recently, I've begun utilising SwiftData, which is proving to be a fantastic tool for managing data within the app. It's been a smooth transition from CoreData.

Below is an example of how you can pre-seed your database using SwiftData.

Country.swift that is Codable:

import SwiftData

@Model
class Country: Codable {
    enum CodingKeys: CodingKey {
        case id
        case name
        case continent
    }

    var id: String = ""
    var name: String = ""
    var continent: String = ""

    init(id: String, name: String, continent: String) {
        self.id = id
        self.name = name
        self.continent = continent
    }

    required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.id = try container.decode(String.self, forKey: .id)
        self.name = try container.decode(String.self, forKey: .name)
        self.continent = try container.decode(String.self, forKey: .continent)
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(id, forKey: .id)
        try container.encode(name, forKey: .name)
        try container.encode(continent, forKey: .continent)
    }
}

In App.swift add this to your window group where you also added your modelContainer (.modelContainer(sharedModelContainer)).

.modelContainer(for: Country.self) { result in
    do {
        let container = try result.get()

        // Check we haven't already added our countries.
        let descriptor = FetchDescriptor<Country>()
        let existingCountries = try container.mainContext.fetchCount(descriptor)
        guard existingCountries == 0 else { return }

        // Load and decode the JSON.
        guard let url = Bundle.main.url(forResource: "countries", withExtension: "json") else {
            fatalError("Failed to find countries.json")
        }

        let data = try Data(contentsOf: url)
        let countries = try JSONDecoder().decode([Country].self, from: data)

        // Add all our data to the context.
        for country in countries {
            container.mainContext.insert(country)
        }
    } catch {
        print("Failed to pre-seed database.")
    }
}
#100DaysToOffload 13/100