@@ -98,8 +98,14 @@ import SwiftUI
9898#else
9999 @preconcurrency @MainActor
100100#endif
101- public final class Store < State, Action> {
101+ public final class Store < State, Action> : _Store {
102102 var children : [ ScopeID < State , Action > : AnyObject ] = [ : ]
103+ private weak var parent : ( any _Store ) ?
104+ private let scopeID : AnyHashable ?
105+
106+ func removeChild( scopeID: AnyHashable ) {
107+ children [ scopeID as! ScopeID < State , Action > ] = nil
108+ }
103109
104110 let core : any Core < State , Action >
105111 @_spi ( Internals) public var effectCancellables : [ UUID : AnyCancellable ] { core. effectCancellables }
@@ -139,6 +145,7 @@ public final class Store<State, Action> {
139145
140146 init ( ) {
141147 self . core = InvalidCore ( )
148+ self . scopeID = nil
142149 }
143150
144151 deinit {
@@ -266,7 +273,7 @@ public final class Store<State, Action> {
266273 let id,
267274 let child = children [ id] as? Store < ChildState , ChildAction >
268275 else {
269- let child = Store < ChildState , ChildAction > ( core: childCore ( ) )
276+ let child = Store < ChildState , ChildAction > ( core: childCore ( ) , scopeID : id , parent : self )
270277 if core. canStoreCacheChildren, let id {
271278 children [ id] = child
272279 }
@@ -313,18 +320,24 @@ public final class Store<State, Action> {
313320 core. send ( action)
314321 }
315322
316- private init ( core: some Core < State , Action > ) {
323+ private init ( core: some Core < State , Action > , scopeID : AnyHashable ? , parent : ( any _Store ) ? ) {
317324 defer { Logger . shared. log ( " \( storeTypeName ( of: self ) ) .init " ) }
318325 self . core = core
326+ self . parent = parent
327+ self . scopeID = scopeID
319328
320329 if let stateType = State . self as? any ObservableState . Type {
321330 func subscribeToDidSet< T: ObservableState > ( _ type: T . Type ) -> AnyCancellable {
322331 return core. didSet
323- . prefix { [ weak self] _ in self ? . core. isInvalid != true }
332+ . prefix { [ weak self] _ in self ? . core. isInvalid == false }
324333 . compactMap { [ weak self] in ( self ? . currentState as? T ) ? . _$id }
325334 . removeDuplicates ( )
326335 . dropFirst ( )
327336 . sink { [ weak self] _ in
337+ guard let scopeID = self ? . scopeID
338+ else { return }
339+ parent? . removeChild ( scopeID: scopeID)
340+ } receiveValue: { [ weak self] _ in
328341 guard let self else { return }
329342 self . _$observationRegistrar. withMutation ( of: self , keyPath: \. currentState) { }
330343 }
@@ -337,7 +350,11 @@ public final class Store<State, Action> {
337350 initialState: R . State ,
338351 reducer: R
339352 ) {
340- self . init ( core: RootCore ( initialState: initialState, reducer: reducer) )
353+ self . init (
354+ core: RootCore ( initialState: initialState, reducer: reducer) ,
355+ scopeID: nil ,
356+ parent: nil
357+ )
341358 }
342359
343360 /// A publisher that emits when state changes.
@@ -565,3 +582,8 @@ let _isStorePerceptionCheckingEnabled: Bool = {
565582 @available ( iOS 17 , macOS 14 , tvOS 17 , watchOS 10 , * )
566583 extension Store : Observable { }
567584#endif
585+
586+ @MainActor
587+ private protocol _Store : AnyObject {
588+ func removeChild( scopeID: AnyHashable )
589+ }
0 commit comments