@@ -485,6 +485,10 @@ public final class Store<State, Action> {
485485 for id in self . children. keys {
486486 self . invalidateChild ( id: id)
487487 }
488+ self . effectCancellables. values. forEach { cancellable in
489+ cancellable. cancel ( )
490+ }
491+ self . effectCancellables. removeAll ( )
488492 }
489493
490494 fileprivate func invalidateChild( id: ScopeID < State , Action > ) {
@@ -526,14 +530,14 @@ public final class Store<State, Action> {
526530 defer { index += 1 }
527531 let action = self . bufferedActions [ index]
528532 let effect = self . reducer. reduce ( into: & currentState, action: action)
533+ let uuid = UUID ( )
529534
530535 switch effect. operation {
531536 case . none:
532537 break
533538 case let . publisher( publisher) :
534539 var didComplete = false
535540 let boxedTask = Box < Task < Void , Never > ? > ( wrappedValue: nil )
536- let uuid = UUID ( )
537541 let effectCancellable = withEscapedDependencies { continuation in
538542 publisher
539543 . handleEvents (
@@ -571,45 +575,48 @@ public final class Store<State, Action> {
571575 }
572576 case let . run( priority, operation) :
573577 withEscapedDependencies { continuation in
574- tasks. wrappedValue. append (
575- Task ( priority: priority) { @MainActor in
576- #if DEBUG
577- let isCompleted = LockIsolated ( false )
578- defer { isCompleted. setValue ( true ) }
579- #endif
580- await operation (
581- Send { effectAction in
582- #if DEBUG
583- if isCompleted. value {
584- runtimeWarn (
585- """
586- An action was sent from a completed effect:
587-
588- Action:
589- \( debugCaseOutput ( effectAction) )
590-
591- Effect returned from:
592- \( debugCaseOutput ( action) )
593-
594- Avoid sending actions using the 'send' argument from 'Effect.run' after \
595- the effect has completed. This can happen if you escape the 'send' \
596- argument in an unstructured context.
597-
598- To fix this, make sure that your 'run' closure does not return until \
599- you're done calling 'send'.
600- """
601- )
602- }
603- #endif
604- if let task = continuation. yield ( {
605- self . send ( effectAction, originatingFrom: action)
606- } ) {
607- tasks. wrappedValue. append ( task)
578+ let task = Task ( priority: priority) { @MainActor [ weak self] in
579+ #if DEBUG
580+ let isCompleted = LockIsolated ( false )
581+ defer { isCompleted. setValue ( true ) }
582+ #endif
583+ await operation (
584+ Send { effectAction in
585+ #if DEBUG
586+ if isCompleted. value {
587+ runtimeWarn (
588+ """
589+ An action was sent from a completed effect:
590+
591+ Action:
592+ \( debugCaseOutput ( effectAction) )
593+
594+ Effect returned from:
595+ \( debugCaseOutput ( action) )
596+
597+ Avoid sending actions using the 'send' argument from 'Effect.run' after \
598+ the effect has completed. This can happen if you escape the 'send' \
599+ argument in an unstructured context.
600+
601+ To fix this, make sure that your 'run' closure does not return until \
602+ you're done calling 'send'.
603+ """
604+ )
608605 }
606+ #endif
607+ if let task = continuation. yield ( {
608+ self ? . send ( effectAction, originatingFrom: action)
609+ } ) {
610+ tasks. wrappedValue. append ( task)
609611 }
610- )
611- }
612- )
612+ }
613+ )
614+ self ? . effectCancellables [ uuid] = nil
615+ }
616+ tasks. wrappedValue. append ( task)
617+ self . effectCancellables [ uuid] = AnyCancellable {
618+ task. cancel ( )
619+ }
613620 }
614621 }
615622 }
0 commit comments