@@ -57,6 +57,8 @@ public struct PresentationState<State> {
5757
5858 private var storage : Storage
5959 @usableFromInline var presentedID : NavigationIDPath ?
60+ // Tracks navigation path when effect was created. Cleared on COW to detect parent context changes.
61+ @usableFromInline var effectNavigationIDPath : NavigationIDPath ? = nil
6062
6163 public init ( wrappedValue: State ? ) {
6264 self . storage = Storage ( state: wrappedValue)
@@ -67,6 +69,7 @@ public struct PresentationState<State> {
6769 set {
6870 if !isKnownUniquelyReferenced( & self . storage) {
6971 self . storage = Storage ( state: newValue)
72+ self . effectNavigationIDPath = nil // Clear on COW to trigger effect recreation
7073 } else {
7174 self . storage. state = newValue
7275 }
@@ -657,9 +660,16 @@ public struct _PresentationReducer<Base: Reducer, Destination: Reducer>: Reducer
657660 baseEffects = self . base. reduce ( into: & state, action: action)
658661 }
659662
663+ let currentNavigationID = state [ keyPath: self . toPresentationState] . wrappedValue. map ( self . navigationIDPath ( for: ) )
664+ let storedEffectPath = initialPresentationState. effectNavigationIDPath
665+
666+ // Detect parent context change: if effectNavigationIDPath is nil but presentation exists,
667+ // it means COW occurred (effectNavigationIDPath was cleared in wrappedValue setter)
668+ let parentContextChanged = currentNavigationID != nil
669+ && ( storedEffectPath == nil || storedEffectPath != currentNavigationID)
670+
660671 let presentationIdentityChanged =
661- initialPresentationState. presentedID
662- != state [ keyPath: self . toPresentationState] . wrappedValue. map ( self . navigationIDPath ( for: ) )
672+ initialPresentationState. presentedID != currentNavigationID
663673
664674 let dismissEffects : Effect < Base . Action >
665675 if presentationIdentityChanged,
@@ -676,14 +686,22 @@ public struct _PresentationReducer<Base: Reducer, Destination: Reducer>: Reducer
676686
677687 if presentationIdentityChanged, state [ keyPath: self . toPresentationState] . wrappedValue == nil {
678688 state [ keyPath: self . toPresentationState] . presentedID = nil
689+ state [ keyPath: self . toPresentationState] . effectNavigationIDPath = nil
679690 }
680691
681692 let presentEffects : Effect < Base . Action >
682- if presentationIdentityChanged || state [ keyPath: self . toPresentationState] . presentedID == nil ,
693+ // Recreate Empty effect if:
694+ // - Parent context changed (COW occurred during enum transition)
695+ // - Presentation identity changed (normal navigation)
696+ // - First time presenting (presentedID is nil)
697+ if ( parentContextChanged
698+ || presentationIdentityChanged
699+ || state [ keyPath: self . toPresentationState] . presentedID == nil ) ,
683700 let presentationState = state [ keyPath: self . toPresentationState] . wrappedValue,
684701 !isEphemeral( presentationState)
685702 {
686703 let presentationDestinationID = self . navigationIDPath ( for: presentationState)
704+ state [ keyPath: self . toPresentationState] . effectNavigationIDPath = presentationDestinationID
687705 state [ keyPath: self . toPresentationState] . presentedID = presentationDestinationID
688706 presentEffects = . concatenate(
689707 . publisher { Empty ( completeImmediately: false ) }
0 commit comments