I have a few crashes on my project that happen in the wild, and the stack trace looks like this, from a thread that is not the main thread:
Crashed: com.apple.SwiftUI.AsyncRenderer
0 libdispatch.dylib 0x36f1c _dispatch_assert_queue_fail + 120
1 libdispatch.dylib 0x37988 dispatch_assert_queue$V2.cold.2 + 114
2 libdispatch.dylib 0x5094 dispatch_assert_queue + 108
3 libdispatch.dylib 0x5094 dispatch_assert_queue$V2 + 108
4 libswift_Concurrency.dylib 0xedfc _swift_task_checkIsolatedSwift + 48
5 libswift_Concurrency.dylib 0x6fc4 swift_task_isCurrentExecutorWithFlagsImpl(swift::SerialExecutorRef, swift::swift_task_is_current_executor_flag) + 356
6 Xogot 0x2585a78 closure #1 in Toolbar3D.dockedBody.getter + 195 (Toolbar3D.swift:195)
7 SwiftUI 0xeae60 ScrollView.init(_:showsIndicators:content:) + 136
8 Xogot 0x2585798 Toolbar3D.body.getter + 207 (Toolbar3D.swift:207)
9 SwiftUICore 0x31614 closure #1 in ViewBodyAccessor.updateBody(of:changed:) + 1068
10 SwiftUICore 0x311b0 ViewBodyAccessor.updateBody(of:changed:) + 348
11 SwiftUICore 0x30f48 protocol witness for BodyAccessor.updateBody(of:changed:) in conformance ViewBodyAccessor<A> + 16
12 SwiftUICore 0x24aa4 closure #1 in DynamicBody.updateValue() + 1136
13 SwiftUICore 0x24224 DynamicBody.updateValue() + 1220
14 SwiftUICore 0x4fffd0 partial apply for implicit closure #1 in closure #1 in closure #1 in Attribute.init<A>(_:) + 32
I have watched the 2025 WWDC Video "Explore Concurrency in SwiftUI" and it does point out that in certain places SwiftUI will use a background thread to run its operations and the documented idiom is that the protocols are non isolated.
The issue is that ScrollView is @MainActor, and the content: argument has no special annotations, so it it flagged as @MainActor, and the new Swift dynamic test asserts.
My class it not that interesting, it looks like this:
struct Toolbar3D: View {
var body: some View {
#if macOS
dockedBody
#else
someOtherBody
#endif
}
var dockedBody: some View {
ScrollView { ... }
}
}
For a second I thought maybe the second layer was the problem, but the stack trace still shows my @MainActor body being invoked by SwiftUI on the background thread.
This is happening in iOS 26.5.0, 26.5.1, iOS 26.5.2, iOS 26.2.0
I am not quite sure how to fix this, short of disabling Swift's dynamic actor isolation (which will probably just crash in a more obscure place at a later point in time).