Search code examples
swiftswiftdata

Fetch models from a background thread SwiftData


I don't need to write, I just need to read.

So far I've found this link, but I'm still very confused. I've not used Actors before, and I'm confused when trying to implement what is explained at that link. So far I haven't been able to get anything they suggest to work.

It seems like this was much simpler using CoreData, as explained here.

Using the code above, it seems that the context and actor are both running on a background thread, but it's still crashing. I assume that that's because the modelContainer is still on the main thread. At least, I'm assuming that the modelContainer is still on the main thread.

How do I fetch Models on a background thread in a thread safe way?


Solution

  • You need to create a new instance of ModelContext and use that but otherwise it can be straightforward to not run a fetch on the main thread.

    Here is a silly example, a basic class that holds its own instance of a ModelContext and performs a fetch count

    class Fetcher {
        let context: ModelContext
    
        init(container: ModelContainer) {
            context = ModelContext(container)
        }
    
        func getSomeStats() async -> Int {
            do {
                return try context.fetchCount(FetchDescriptor<TransactionDTO>())
            } catch {
                print(error)
                return 0
            }
        }
    }
    

    If you call it like this

    .task {
        let fetcher = Fetcher(container: modelContext.container)
        let result = await fetcher.getSomeStats()
        print(result)
    }
    

    and set a breakpoint inside getSomeStats you will clearly see it isn't running on the main thread.