diff --git a/ios/RNSScreen.mm b/ios/RNSScreen.mm index fdbe45af28..ca87266b5d 100644 --- a/ios/RNSScreen.mm +++ b/ios/RNSScreen.mm @@ -41,6 +41,7 @@ #import "RNSDefines.h" #import "UIView+RNSUtility.h" +#import "integrations/RNSLifecycleListenerProtocol.h" #ifdef RCT_NEW_ARCH_ENABLED namespace react = facebook::react; @@ -76,6 +77,7 @@ @implementation RNSScreenView { ContentWrapperBox _contentWrapperBox; bool _sheetHasInitialDetentSet; BOOL _shouldUpdateScrollEdgeEffects; + RNSScreen *_controllerBeforeInvalidate; #ifdef RCT_NEW_ARCH_ENABLED RCTSurfaceTouchHandler *_touchHandler; react::RNSScreenShadowNode::ConcreteState::Shared _state; @@ -630,6 +632,26 @@ - (void)notifyWillDisappear if (_hideKeyboardOnSwipe) { [self endEditing:YES]; } + + // Notify any presented view controllers that conform to RNSLifecycleListenerProtocol + RNSScreen *controller = _controller ?: _controllerBeforeInvalidate; + if (controller) { + UIViewController *presented = controller.presentedViewController; + while (presented) { + UIViewController *next = presented.presentedViewController; + if ([presented conformsToProtocol:@protocol(RNSLifecycleListenerProtocol)]) { + BOOL isPresenterUnmounting = NO; + RNSScreen *presenter = (RNSScreen *)presented.presentingViewController; + if ([presenter isKindOfClass:[RNSScreen class]]) { + isPresenterUnmounting = presenter.screenView.isMarkedForUnmountInCurrentTransaction; + } + [(id)presented screenWillDisappear:controller + isPresenterUnmounting:isPresenterUnmounting]; + } + presented = next; + } + } + #ifdef RCT_NEW_ARCH_ENABLED // If screen is already unmounted then there will be no event emitter if (_eventEmitter != nullptr) { @@ -965,6 +987,9 @@ - (BOOL)isTransparentModal - (void)invalidateImpl { + if (_controller && !_controllerBeforeInvalidate) { + _controllerBeforeInvalidate = _controller; + } _controller = nil; [_sheetsScrollView removeObserver:self forKeyPath:@"bounds" context:nil]; } diff --git a/ios/integrations/RNSLifecycleListenerProtocol.h b/ios/integrations/RNSLifecycleListenerProtocol.h new file mode 100644 index 0000000000..025b4231c0 --- /dev/null +++ b/ios/integrations/RNSLifecycleListenerProtocol.h @@ -0,0 +1,14 @@ +#import + +NS_ASSUME_NONNULL_BEGIN + +@protocol RNSLifecycleListenerProtocol + +// Called when a screen in the presenting hierarchy is about to disappear. +// @param screen The screen controller that is disappearing +// @param isPresenterUnmounting YES if the presenter (modal) itself is being unmounted +- (void)screenWillDisappear:(UIViewController *)screen isPresenterUnmounting:(BOOL)isPresenterUnmounting; + +@end + +NS_ASSUME_NONNULL_END