@@ -93,14 +93,6 @@ import SwiftUI
9393/// package when targeting iOS <17) by applying the ``ObservableState()`` macro to your feature's
9494/// state.
9595
96-
97- @MainActor
98- protocol _Store : AnyObject {
99- var allChildren : [ AnyObject ] { get }
100- func removeChild( _ store: AnyObject )
101- }
102-
103-
10496@dynamicMemberLookup
10597#if swift(<5.10)
10698 @MainActor ( unsafe)
@@ -109,16 +101,11 @@ protocol _Store: AnyObject {
109101#endif
110102public final class Store < State, Action> : _Store {
111103 var children : [ ScopeID < State , Action > : AnyObject ] = [ : ]
104+ private weak var parent : ( any _Store ) ?
105+ private let scopeID : AnyHashable ?
112106
113- var allChildren : [ AnyObject ] {
114- Array ( children. values)
115- }
116- func removeChild( _ store: AnyObject ) {
117- for (key, child) in children {
118- guard child === store
119- else { continue }
120- children. removeValue ( forKey: key)
121- }
107+ func removeChild( scopeID: AnyHashable ) {
108+ children [ scopeID as! ScopeID < State , Action > ] = nil
122109 }
123110
124111 let core : any Core < State , Action >
@@ -159,6 +146,7 @@ public final class Store<State, Action>: _Store {
159146
160147 init ( ) {
161148 self . core = InvalidCore ( )
149+ self . scopeID = nil
162150 }
163151
164152 deinit {
@@ -286,7 +274,7 @@ public final class Store<State, Action>: _Store {
286274 let id,
287275 let child = children [ id] as? Store < ChildState , ChildAction >
288276 else {
289- let child = Store < ChildState , ChildAction > ( core: childCore ( ) , parent: self )
277+ let child = Store < ChildState , ChildAction > ( core: childCore ( ) , scopeID : id , parent: self )
290278 if core. canStoreCacheChildren, let id {
291279 children [ id] = child
292280 }
@@ -333,28 +321,24 @@ public final class Store<State, Action>: _Store {
333321 core. send ( action)
334322 }
335323
336- private weak var parent : ( any _Store ) ?
337-
338- private init ( core: some Core < State , Action > , parent: ( any _Store ) ? ) {
339- defer { Logger . shared. log ( " \( storeTypeName ( of: self ) ) .init " ) }
324+ private init ( core: some Core < State , Action > , scopeID: AnyHashable ? , parent: ( any _Store ) ? ) {
325+ defer { Logger . shared. log ( " \( storeTypeName ( of: self ) ) .init " ) }
340326 self . core = core
341327 self . parent = parent
328+ self . scopeID = scopeID
342329
343330 if let stateType = State . self as? any ObservableState . Type {
344331 func subscribeToDidSet< T: ObservableState > ( _ type: T . Type ) -> AnyCancellable {
345332 return core. didSet
346- . prefix { [ weak self] _ in
347- guard let self else { return false }
348- let isInvalid = self . core. isInvalid
349- if isInvalid {
350- self . parent? . removeChild ( self )
351- }
352- return !isInvalid
353- }
333+ . prefix { [ weak self] _ in self ? . core. isInvalid == false }
354334 . compactMap { [ weak self] in ( self ? . currentState as? T ) ? . _$id }
355335 . removeDuplicates ( )
356336 . dropFirst ( )
357337 . sink { [ weak self] _ in
338+ guard let scopeID = self ? . scopeID
339+ else { return }
340+ parent? . removeChild ( scopeID: scopeID)
341+ } receiveValue: { [ weak self] _ in
358342 guard let self else { return }
359343 self . _$observationRegistrar. withMutation ( of: self , keyPath: \. currentState) { }
360344 }
@@ -367,7 +351,11 @@ public final class Store<State, Action>: _Store {
367351 initialState: R . State ,
368352 reducer: R
369353 ) {
370- self . init ( core: RootCore ( initialState: initialState, reducer: reducer) , parent: nil )
354+ self . init (
355+ core: RootCore ( initialState: initialState, reducer: reducer) ,
356+ scopeID: nil ,
357+ parent: nil
358+ )
371359 }
372360
373361 /// A publisher that emits when state changes.
@@ -595,3 +583,8 @@ let _isStorePerceptionCheckingEnabled: Bool = {
595583 @available ( iOS 17 , macOS 14 , tvOS 17 , watchOS 10 , * )
596584 extension Store : Observable { }
597585#endif
586+
587+ @MainActor
588+ private protocol _Store : AnyObject {
589+ func removeChild( scopeID: AnyHashable )
590+ }
0 commit comments