-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Store: ObservableObject #3625
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Store: ObservableObject #3625
Conversation
|
@stephencelis Should we not provide something like this instead of conforming to protocols without proper implementation? import SwiftUI
import ComposableArchitecture
/// A property wrapper that mimics `@StateObject` for root-level TCA features.
///
/// Useful when your feature has no parent (e.g. in your `App`, modal entry point, or top-level view).
/// Ensures the store is only initialized once.
///
/// ```swift
/// @RootStore(MyFeature(), state: MyFeature.State()) var store
/// ```
@MainActor
@propertyWrapper
struct RootStore<R>: @preconcurrency DynamicProperty where R: Reducer {
@State private var storage: Storage
var wrappedValue: StoreOf<R> { storage.store }
var projectedValue: Perception.Bindable<StoreOf<R>> {
.init(wrappedValue)
}
init(
_ reducer: @escaping @autoclosure () -> R,
state initialState: @escaping @autoclosure () -> R.State,
withDependencies prepareDependencies: ((inout DependencyValues) -> Void)? = nil
) {
self._storage = .init(initialValue: .init(makeStore: {
.init(initialState: initialState(), reducer: reducer, withDependencies: prepareDependencies)
}))
}
func update() {
storage.update()
}
@Perceptible
fileprivate final class Storage {
private let makeStore: () -> StoreOf<R>
private(set) var store: StoreOf<R>!
init(makeStore: @escaping () -> StoreOf<R>) {
self.makeStore = makeStore
}
func update() {
guard store == nil else { return }
store = makeStore()
}
}
} |
|
@arnauddorgans The main reason we want to support And while we considered a custom property wrapper, it's not only additional API surface area to learn about and maintain, but we think Apple probably is better equipped to provide such an API and any internals it uses than us. We're down to chat about this further if you think it's worth it, but want to start a dedicated discussion? |
|
@stephencelis I am just afraid about the fact that a SwiftUI view observes changes from StateObject based on ObservableObject protocol, but as the Store is Observable and not ObservableObject, we do not send events to the objectWillChange publisher Is it safe? Are we not afraid that internal SwiftUI logic makes us miss view updates? |
|
@arnauddorgans We don't believe it is a problem but we can revisit if you encounter any! |
We can add an
ObservableObjectconformance toStoreso that it can be held in@StateObject. This conformance is inert and should not imply that the store is observable as an@ObservedObject.