diff --git a/Sources/Atoms/AtomRoot.swift b/Sources/Atoms/AtomRoot.swift index 12439222..b238bd68 100644 --- a/Sources/Atoms/AtomRoot.swift +++ b/Sources/Atoms/AtomRoot.swift @@ -61,7 +61,7 @@ import SwiftUI /// ``` /// public struct AtomRoot: View { - private var storeHost: StoreHost + private var storage: Storage private var overrides = [OverrideKey: any OverrideProtocol]() private var observers = [Observer]() private let content: Content @@ -70,7 +70,7 @@ public struct AtomRoot: View { /// /// - Parameter content: The descendant view content that provides context for atoms. public init(@ViewBuilder content: () -> Content) { - self.storeHost = .tree + self.storage = .managed self.content = content() } @@ -84,26 +84,26 @@ public struct AtomRoot: View { storesIn store: AtomStore, @ViewBuilder content: () -> Content ) { - self.storeHost = .unmanaged(store: store) + self.storage = .unmanaged(store: store) self.content = content() } /// The content and behavior of the view. public var body: some View { - switch storeHost { - case .tree: - TreeManaged( - content: content, + switch storage { + case .managed: + Managed( overrides: overrides, - observers: observers + observers: observers, + content: content ) case .unmanaged(let store): Unmanaged( - content: content, store: store, overrides: overrides, - observers: observers + observers: observers, + content: content ) } } @@ -150,31 +150,28 @@ public struct AtomRoot: View { } private extension AtomRoot { - enum StoreHost { - case tree + enum Storage { + case managed case unmanaged(store: AtomStore) } - struct TreeManaged: View { - @MainActor - final class State: ObservableObject { - let store = AtomStore() - let token = ScopeKey.Token() - } - - let content: Content + struct Managed: View { let overrides: [OverrideKey: any OverrideProtocol] let observers: [Observer] + let content: Content + + @State + private var store = AtomStore() - @StateObject - private var state = State() + @State + private var token = ScopeKey.Token() var body: some View { content.environment( \.store, StoreContext( - store: state.store, - scopeKey: ScopeKey(token: state.token), + store: store, + scopeKey: ScopeKey(token: token), inheritedScopeKeys: [:], observers: observers, scopedObservers: [], @@ -186,25 +183,20 @@ private extension AtomRoot { } struct Unmanaged: View { - @MainActor - final class State: ObservableObject { - let token = ScopeKey.Token() - } - - let content: Content let store: AtomStore let overrides: [OverrideKey: any OverrideProtocol] let observers: [Observer] + let content: Content - @StateObject - private var state = State() + @State + private var token = ScopeKey.Token() var body: some View { content.environment( \.store, StoreContext( store: store, - scopeKey: ScopeKey(token: state.token), + scopeKey: ScopeKey(token: token), inheritedScopeKeys: [:], observers: observers, scopedObservers: [], diff --git a/Sources/Atoms/AtomScope.swift b/Sources/Atoms/AtomScope.swift index e401132f..d0ff25b9 100644 --- a/Sources/Atoms/AtomScope.swift +++ b/Sources/Atoms/AtomScope.swift @@ -87,19 +87,19 @@ public struct AtomScope: View { public var body: some View { switch inheritance { case .environment(let id): - InheritedEnvironment( + WithEnvironment( id: id, - content: content, overrides: overrides, - observers: observers + observers: observers, + content: content ) case .context(let store): - InheritedContext( - content: content, + WithContext( store: store, overrides: overrides, - observers: observers + observers: observers, + content: content ) } } @@ -158,19 +158,15 @@ private extension AtomScope { case context(store: StoreContext) } - struct InheritedEnvironment: View { - @MainActor - final class State: ObservableObject { - let token = ScopeKey.Token() - } - + struct WithEnvironment: View { let id: ScopeID - let content: Content let overrides: [OverrideKey: any OverrideProtocol] let observers: [Observer] + let content: Content + + @State + private var token = ScopeKey.Token() - @StateObject - private var state = State() @Environment(\.store) private var environmentStore @@ -178,7 +174,7 @@ private extension AtomScope { content.environment( \.store, environmentStore?.scoped( - scopeKey: ScopeKey(token: state.token), + scopeKey: ScopeKey(token: token), scopeID: id, observers: observers, overrides: overrides @@ -187,11 +183,11 @@ private extension AtomScope { } } - struct InheritedContext: View { - let content: Content + struct WithContext: View { let store: StoreContext let overrides: [OverrideKey: any OverrideProtocol] let observers: [Observer] + let content: Content var body: some View { content.environment( diff --git a/Sources/Atoms/PropertyWrapper/ViewContext.swift b/Sources/Atoms/PropertyWrapper/ViewContext.swift index 29abc64c..fefdd93d 100644 --- a/Sources/Atoms/PropertyWrapper/ViewContext.swift +++ b/Sources/Atoms/PropertyWrapper/ViewContext.swift @@ -32,8 +32,11 @@ import SwiftUI /// @propertyWrapper public struct ViewContext: DynamicProperty { - @StateObject - private var state = State() + @State + private var phase = false + + @State + private var subscriberState = SubscriberState() @Environment(\.store) private var _store @@ -54,13 +57,18 @@ public struct ViewContext: DynamicProperty { /// Instead, you use the property variable created with the `@ViewContext` attribute. @MainActor public var wrappedValue: AtomViewContext { - AtomViewContext( + let phase = $phase + + // Initializes State and starts observing for updates. + _ = phase.wrappedValue + + return AtomViewContext( store: store, - subscriber: Subscriber(state.subscriberState), + subscriber: Subscriber(subscriberState), subscription: Subscription( location: location, - update: { [weak state] in - state?.objectWillChange.send() + update: { + phase.wrappedValue.toggle() } ) ) @@ -68,11 +76,6 @@ public struct ViewContext: DynamicProperty { } private extension ViewContext { - @MainActor - final class State: ObservableObject { - let subscriberState = SubscriberState() - } - @MainActor var store: StoreContext { guard let _store else {