SwiftData crash Task isolating closure inside AsyncStream in @Observable viewmodel?

19 hours ago 1
ARTICLE AD BOX

I'm losing my mind here. I just upgraded my project to use the new @Observable macro and SwiftData instead of CoreData. Everything was working fine until I tried to implement a real-time network sync that streams data updates using AsyncStream.

Every time the stream yields a new item and I try to insert or update it in my ModelContext, the app crashes with a crazy concurrency error or straight up EXC_BAD_ACCESS.

Here is my setup. I have a NetworkMonitor that yields IDs over an async stream. Inside my View Model (which is marked with @Observable), I listen to this stream in a Task.

// My Model @Model class TodoItem { var id: UUID var title: String var isDone: Bool init(id: UUID, title: String, isDone: Bool = false) { self.id = id self.title = title self.isDone = isDone } } // The ViewModel causing the crash @Observable class TodoViewModel { var items: [TodoItem] = [] private var modelContext: ModelContext private var networkSync = NetworkSyncManager() // returns AsyncStream<String> init(modelContext: ModelContext) { self.modelContext = modelContext } func listenToSync() { Task { // Crash happens somewhere inside here for await rawUpdate in networkSync.updateStream { let newItem = TodoItem(id: UUID(), title: "Synced: \(rawUpdate)") // CRASH HERE: "Mutation of captured var 'self' in concurrently-executing code" // Or sometimes: Thread 3: Fatal error: Illegal attempt to map a non-Sendable type self.modelContext.insert(newItem) try? self.modelContext.save() } } } }

If I remove self.modelContext.insert(newItem), the loop runs fine and prints the strings.

What am I doing wrong? Is @Observable making the view model MainActor? If Task inherits MainActor, why is it complaining about concurrently-executing code? I tried adding @MainActor to the class, but then I get compiler errors on the for await line saying MainActor-isolated property cannot be mutated from a non-isolated context.

Any help is appreciated, I'm completely stuck.

Read Entire Article