Non-main thread warning when calling using .refreshable from child @ViewBuilder property
Closed this issue · 1 comments
Description
If you add the .refreshable
modifier to the child property in @ViewBuilder
, attempting to refresh the list triggers a warning that the call was made on a non-main thread:
"Store.send" was called on a non-main thread with: Test.Action.refresh …
The "Store" class is not thread-safe, and so all interactions with an instance of "Store" (including all of its scopes and derived view stores) must be done on the main thread.
received action:
Test.Action.refresh
(No state changes)received action:
Test.Action.increment
Test.State(
- _count: 0
- _count: 1
)
Example:
struct TestView: View {
let store: StoreOf<Test>
var body: some View {
NavigationStack {
list
}
}
@ViewBuilder
var list: some View {
List {
Text(verbatim: "Count: \(store.count)")
}
.refreshable {
await store.send(.refresh).finish()
}
}
}
However, if you place the list directly in the body, everything works as expected without warnings:
received action:
Test.Action.refresh
(No state changes)received action:
Test.Action.increment
Test.State(
- _count: 0
- _count: 1
)
Example:
struct TestView: View {
let store: StoreOf<Test>
var body: some View {
NavigationStack {
List {
Text(verbatim: "Count: \(store.count)")
}
.refreshable {
await store.send(.refresh).finish()
}
}
}
}
Checklist
- I have determined whether this bug is also reproducible in a vanilla SwiftUI project.
- If possible, I've reproduced the issue using the
main
branch of this package. - This issue hasn't been addressed in an existing GitHub issue or discussion.
Expected behavior
No non-main thread warning
Actual behavior
Store.send" was called on a non-main thread with: Test.Action.refresh …
The "Store" class is not thread-safe, and so all interactions with an instance of "Store" (including all of its scopes and derived view stores) must be done on the main thread.
Steps to reproduce
No response
The Composable Architecture version information
1.10.3
Destination operating system
iOS 17.4
Xcode version information
Version 15.3 (15E204a)
Swift Compiler version information
swift-driver version: 1.90.11.1 Apple Swift version 5.10 (swiftlang-5.10.0.13 clang-1500.3.9.4)
Target: arm64-apple-macosx14.0
Hi @uniqby, this is just how Swift/SwiftUI behaves, for better or worse. The body
of views is marked as @MainActor(unsafe)
, and so everything inside inherits @MainActor
, including refreshable
. But as soon as you move some of the view out to another computed property, it loses the @MainActor
. You can either mark the list
property as @MainActor
, or you can use refreshable { @MainActor in … }
.
Since this is not an issue with the library I am going to convert it to a discussion. Feel to free to continue the conversation over there.