@@ -171,12 +171,10 @@ - (void)setStackPresentation:(RNSScreenStackPresentation)stackPresentation
171171 _controller.presentationController .delegate = self;
172172 } else if (_stackPresentation != RNSScreenStackPresentationPush) {
173173#ifdef RCT_NEW_ARCH_ENABLED
174- // TODO: on Fabric, same controllers can be used as modals and then recycled and used a push which would result in
175- // this error. It would be good to check if it doesn't leak in such case.
176174#else
177175 RCTLogError (
178176 @" Screen presentation updated from modal to push, this may likely result in a screen object leakage. If you need to change presentation style create a new screen object instead" );
179- #endif
177+ #endif // RCT_NEW_ARCH_ENABLED
180178 }
181179 _stackPresentation = stackPresentation;
182180}
@@ -298,7 +296,6 @@ - (void)notifyDismissedWithCount:(int)dismissCount
298296{
299297#ifdef RCT_NEW_ARCH_ENABLED
300298 // If screen is already unmounted then there will be no event emitter
301- // it will be cleaned in prepareForRecycle
302299 if (_eventEmitter != nullptr ) {
303300 std::dynamic_pointer_cast<const react::RNSScreenEventEmitter>(_eventEmitter)
304301 ->onDismissed (react::RNSScreenEventEmitter::OnDismissed{.dismissCount = dismissCount});
@@ -320,7 +317,6 @@ - (void)notifyDismissCancelledWithDismissCount:(int)dismissCount
320317{
321318#ifdef RCT_NEW_ARCH_ENABLED
322319 // If screen is already unmounted then there will be no event emitter
323- // it will be cleaned in prepareForRecycle
324320 if (_eventEmitter != nullptr ) {
325321 std::dynamic_pointer_cast<const react::RNSScreenEventEmitter>(_eventEmitter)
326322 ->onNativeDismissCancelled (
@@ -337,7 +333,6 @@ - (void)notifyWillAppear
337333{
338334#ifdef RCT_NEW_ARCH_ENABLED
339335 // If screen is already unmounted then there will be no event emitter
340- // it will be cleaned in prepareForRecycle
341336 if (_eventEmitter != nullptr ) {
342337 std::dynamic_pointer_cast<const react::RNSScreenEventEmitter>(_eventEmitter)
343338 ->onWillAppear (react::RNSScreenEventEmitter::OnWillAppear{});
@@ -360,7 +355,6 @@ - (void)notifyWillDisappear
360355 }
361356#ifdef RCT_NEW_ARCH_ENABLED
362357 // If screen is already unmounted then there will be no event emitter
363- // it will be cleaned in prepareForRecycle
364358 if (_eventEmitter != nullptr ) {
365359 std::dynamic_pointer_cast<const react::RNSScreenEventEmitter>(_eventEmitter)
366360 ->onWillDisappear (react::RNSScreenEventEmitter::OnWillDisappear{});
@@ -376,7 +370,6 @@ - (void)notifyAppear
376370{
377371#ifdef RCT_NEW_ARCH_ENABLED
378372 // If screen is already unmounted then there will be no event emitter
379- // it will be cleaned in prepareForRecycle
380373 if (_eventEmitter != nullptr ) {
381374 std::dynamic_pointer_cast<const react::RNSScreenEventEmitter>(_eventEmitter)
382375 ->onAppear (react::RNSScreenEventEmitter::OnAppear{});
@@ -396,7 +389,6 @@ - (void)notifyDisappear
396389{
397390#ifdef RCT_NEW_ARCH_ENABLED
398391 // If screen is already unmounted then there will be no event emitter
399- // it will be cleaned in prepareForRecycle
400392 if (_eventEmitter != nullptr ) {
401393 std::dynamic_pointer_cast<const react::RNSScreenEventEmitter>(_eventEmitter)
402394 ->onDisappear (react::RNSScreenEventEmitter::OnDisappear{});
@@ -676,6 +668,11 @@ - (BOOL)hasHeaderConfig
676668 return react::concreteComponentDescriptorProvider<react::RNSScreenComponentDescriptor>();
677669}
678670
671+ + (BOOL )shouldBeRecycled
672+ {
673+ return NO ;
674+ }
675+
679676- (void )mountChildComponentView : (UIView<RCTComponentViewProtocol> *)childComponentView index : (NSInteger )index
680677{
681678 if ([childComponentView isKindOfClass: [RNSScreenStackHeaderConfig class ]]) {
@@ -697,27 +694,6 @@ - (void)unmountChildComponentView:(UIView<RCTComponentViewProtocol> *)childCompo
697694
698695#pragma mark - RCTComponentViewProtocol
699696
700- - (void )prepareForRecycle
701- {
702- [super prepareForRecycle ];
703- // TODO: Make sure that there is no edge case when this should be uncommented
704- // _controller=nil;
705- _dismissed = NO ;
706- _state.reset ();
707- _touchHandler = nil ;
708-
709- // We set this prop to default value here to workaround view-recycling.
710- // Let's assume the view has had _stackPresentation == <some modal stack presentation> set
711- // before below line was executed. Then, when instantiated again (with the same modal presentation)
712- // updateProps:oldProps: method would be called and setter for stack presentation would not be called.
713- // This is crucial as in that setter we register `self.controller` as a delegate
714- // (UIAdaptivePresentationControllerDelegate) to presentation controller and this leads to buggy modal behaviour as we
715- // rely on UIAdaptivePresentationControllerDelegate callbacks. Restoring the default value and then comparing against
716- // it in updateProps:oldProps: allows for setter to be called, however if there was some additional logic to execute
717- // when stackPresentation is set to "push" the setter would not be triggered.
718- _stackPresentation = RNSScreenStackPresentationPush;
719- }
720-
721697- (void )updateProps : (react::Props::Shared const &)props oldProps : (react::Props::Shared const &)oldProps
722698{
723699 const auto &oldScreenProps = *std::static_pointer_cast<const react::RNSScreenProps>(_props);
@@ -781,12 +757,9 @@ - (void)updateProps:(react::Props::Shared const &)props oldProps:(react::Props::
781757 }
782758#endif // !TARGET_OS_TV
783759
784- // Notice that we compare against _stackPresentation, not oldScreenProps.stackPresentation.
785- // See comment in prepareForRecycle method for explanation.
786- RNSScreenStackPresentation newStackPresentation =
787- [RNSConvert RNSScreenStackPresentationFromCppEquivalent: newScreenProps.stackPresentation];
788- if (newStackPresentation != _stackPresentation) {
789- [self setStackPresentation: newStackPresentation];
760+ if (newScreenProps.stackPresentation != oldScreenProps.stackPresentation ) {
761+ [self
762+ setStackPresentation: [RNSConvert RNSScreenStackPresentationFromCppEquivalent: newScreenProps.stackPresentation]];
790763 }
791764
792765 if (newScreenProps.stackAnimation != oldScreenProps.stackAnimation ) {
@@ -993,9 +966,6 @@ - (void)viewDidAppear:(BOOL)animated
993966- (void )viewDidDisappear : (BOOL )animated
994967{
995968 [super viewDidDisappear: animated];
996- #ifdef RCT_NEW_ARCH_ENABLED
997- [self resetViewToScreen ];
998- #endif
999969 if (self.parentViewController == nil && self.presentingViewController == nil ) {
1000970 if (self.screenView .preventNativeDismiss ) {
1001971 // if we want to prevent the native dismiss, we do not send dismissal event,
@@ -1411,25 +1381,10 @@ - (void)hideHeaderIfNecessary
14111381
14121382- (void )setViewToSnapshot : (UIView *)snapshot
14131383{
1414- // modals of native stack seem not to support
1415- // changing their view by just setting the view
1416- if (_initialView.stackPresentation != RNSScreenStackPresentationPush) {
1417- UIView *superView = self.view .superview ;
1418- [self .view removeFromSuperview ];
1419- self.view = snapshot;
1420- [superView addSubview: self .view];
1421- } else {
1422- [self .view removeFromSuperview ];
1423- self.view = snapshot;
1424- }
1425- }
1426-
1427- - (void )resetViewToScreen
1428- {
1429- if (self.view != _initialView) {
1430- [self .view removeFromSuperview ];
1431- self.view = _initialView;
1432- }
1384+ UIView *superView = self.view .superview ;
1385+ [self .view removeFromSuperview ];
1386+ self.view = snapshot;
1387+ [superView addSubview: self .view];
14331388}
14341389
14351390#else
0 commit comments