@@ -42,7 +42,82 @@ - (void)mergeChildOptions:(RNNNavigationOptions *)options child:(UIViewControlle
4242
4343- (UIViewController *)popViewControllerAnimated : (BOOL )animated {
4444 [self prepareForPop ];
45- return [super popViewControllerAnimated: animated];
45+ UIViewController *previousTop = self.topViewController ;
46+ UIView *snapshot = [self snapshotTopView: animated];
47+
48+ UIViewController *poppedVC = [super popViewControllerAnimated: animated];
49+ if (!poppedVC) {
50+ [snapshot removeFromSuperview ];
51+ return nil ;
52+ }
53+
54+ id <UIViewControllerTransitionCoordinator> coordinator = self.transitionCoordinator ;
55+ if (coordinator && coordinator.isInteractive ) {
56+ // Interactive pop (swipe-back): remove snapshot overlay — UIKit shows the live
57+ // view during the gesture. Skip early teardown so the React view stays alive
58+ // if the gesture is cancelled. The delegate's didShowViewController handles
59+ // cleanup once the animation finishes.
60+ [snapshot removeFromSuperview ];
61+ } else {
62+ [self teardownPoppedControllers: @[ poppedVC ] previousTop: previousTop];
63+ }
64+ return poppedVC;
65+ }
66+
67+ - (NSArray <UIViewController *> *)popToViewController : (UIViewController *)viewController
68+ animated : (BOOL )animated {
69+ UIViewController *previousTop = self.topViewController ;
70+ UIView *snapshot = [self snapshotTopView: animated];
71+
72+ NSArray <UIViewController *> *poppedVCs =
73+ [super popToViewController: viewController animated: animated];
74+ if (poppedVCs.count > 0 ) {
75+ [self teardownPoppedControllers: poppedVCs previousTop: previousTop];
76+ } else {
77+ [snapshot removeFromSuperview ];
78+ }
79+ return poppedVCs;
80+ }
81+
82+ - (NSArray <UIViewController *> *)popToRootViewControllerAnimated : (BOOL )animated {
83+ UIViewController *previousTop = self.topViewController ;
84+ UIView *snapshot = [self snapshotTopView: animated];
85+
86+ NSArray <UIViewController *> *poppedVCs =
87+ [super popToRootViewControllerAnimated: animated];
88+ if (poppedVCs.count > 0 ) {
89+ [self teardownPoppedControllers: poppedVCs previousTop: previousTop];
90+ } else {
91+ [snapshot removeFromSuperview ];
92+ }
93+ return poppedVCs;
94+ }
95+
96+ #pragma mark - React view teardown
97+
98+ - (UIView *)snapshotTopView : (BOOL )animated {
99+ if (!animated) return nil ;
100+ UIViewController *topVC = self.topViewController ;
101+ if (!topVC.isViewLoaded || !topVC.view .window ) return nil ;
102+
103+ UIView *snapshot = [topVC.view snapshotViewAfterScreenUpdates: NO ];
104+ if (snapshot) {
105+ snapshot.frame = topVC.view .bounds ;
106+ snapshot.autoresizingMask =
107+ UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
108+ [topVC.view addSubview: snapshot];
109+ }
110+ return snapshot;
111+ }
112+
113+ - (void )teardownPoppedControllers : (NSArray <UIViewController *> *)poppedVCs
114+ previousTop : (UIViewController *)previousTop {
115+ for (UIViewController *vc in poppedVCs) {
116+ if (vc == previousTop && [vc isKindOfClass: [RNNComponentViewController class ]]) {
117+ [[(RNNComponentViewController *)vc reactView ] componentDidDisappear ];
118+ }
119+ [vc destroyReactView ];
120+ }
46121}
47122
48123- (BOOL )navigationBar : (UINavigationBar *)navigationBar shouldPopItem : (UINavigationItem *)item {
0 commit comments