Skip to main content

How to use SwiftData to store singletons

About 1 minSwiftArticle(s)bloghackingwithswift.comcrashcourseswiftswiftdataxcodeappstore

How to use SwiftData to store singletons 관련

SwiftData by Example

Back to Home

How to use SwiftData to store singletons | SwiftData by Example

How to use SwiftData to store singletons

Updated for Xcode 15

Given how easy SwiftData makes data storage, you’re likely to be tempted to want to use it for general app storage such as settings and more. However, this takes a little more work because the @Query macro is designed to return collections of model objects rather than a single instance.

They here is to create a custom fetch request to read the whole collection of results, then simply return the first one to get your data, or create a fresh instance if there was nothing already saved.

As an example, we might have an AppSettings model such as this one:

@Model class AppSettings {
    var name: String
    var location: String
    var selectedTopics: [String]

    init(name: String, location: String, selectedTopics: [String]) {
        self.name = name
        self.location = location
        self.selectedTopics = selectedTopics
    }
}

We could then load that either at app launch, or using onAppear() inside a root view such as this:

struct ContentView: View {
    @Environment(\.modelContext) var modelContext
    @State private var settings: AppSettings?

    var body: some View {
        NavigationStack {
            VStack {
                if let settings {
                    Text("Name: \(settings.name)")
                    Text("Location: \(settings.location)")
                    Text("Topics: \(settings.selectedTopics.formatted(.list(type: .and)))")
                } else {
                    Text("Loading…")
                }
            }
            .navigationTitle("Singletons")
            .onAppear(perform: load)
        }
    }

    func load() {
        let request = FetchDescriptor<AppSettings>()
        let data = try? modelContext.fetch(request)
        settings = data?.first ?? AppSettings(name: "Anonymous", location: "Unknown", selectedTopics: ["Latest News"])
    }
}

While this approach definitely works, it’s worth asking whether it’s the best option – would using a simple Codable type work better, for example?

Note

Although SwiftData supports working with document-based apps, it does not provide the document as a singleton inside there – you still need to issue a query for a collection of results.


이찬희 (MarkiiimarK)
Never Stop Learning.