-
-
Notifications
You must be signed in to change notification settings - Fork 599
fix(IOS): Fix non dismissible modal presentation #3415
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
fix(IOS): Fix non dismissible modal presentation #3415
Conversation
When a modal conforms to RNSDismissibleModalProtocol and returns NO from isDismissible, it should not be dismissed when new modals are presented. Previously, when isDismissible returned NO, the code would skip the entire dismissal block, including the logic that updates changeRootController to handle the presentation hierarchy correctly. This caused iOS to throw an error because it tried to present a new modal from a view controller that was already presenting the non-dismissible modal. This fix: - Extracts the dismissibility check into a clear boolean variable - Adds an else clause that runs when a modal is non-dismissible - Updates changeRootController to be the non-dismissible modal - Checks if the non-dismissible modal has presented any RN modals - Properly dismisses RN modals presented by the non-dismissible modal This enables third-party modal libraries (like TrueSheet, react-native-modal, etc.) to coexist with React Navigation modals by implementing the protocol. Example use case: - User opens a bottom sheet (TrueSheet) from a screen - User taps a button in the sheet to open a React Navigation modal - Modal presents successfully from the sheet - Modal can be dismissed while sheet remains open Fixes presentation errors like: "Attempt to present <RNSScreen> on <UIViewController> which is already presenting <ThirdPartyModal>" Related: Implements proper support for RNSDismissibleModalProtocol
|
@kkafar an alternative approach would be to create another method to the protocol to return a ViewController that should update the root controller to keep things safe. Let me know if that's better. Thank you! |
…ting controller - Add presentingControllerForModals optional method to RNSDismissibleModalProtocol - Allow external non-dismissible modals to provide their own presenting controller - Only use external controller if explicitly provided (non-nil) - Falls back to original implementation if method not implemented or returns nil - Add UIKit import to protocol header for UIViewController support
|
Can we merge this @kligarski @kkafar? This should be straightforward and backwards compatible. Tested and works in a production app. Thank you! FYI @erickreutz |
|
Hey, sorry for very late response here & on other PRs. I'll look into this after we release 4.19.0 (planned for upcoming week). |
Description
This PR fixes an issue with the modal presentation chain when non-dismissible external modals (e.g., third-party modals like TrueSheet) are present in the view controller hierarchy.
Previously, when a non-dismissible modal was encountered, the stack didn't properly update the root controller for subsequent modal presentations, which could cause modals to be presented from the wrong controller or fail to dismiss modals that were presented by the non-dismissible modal.
Changes
RNSScreenStack.mm:elsebranch to handle the case whenfirstModalToBeDismissedis non-dismissiblechangeRootControlleris now updated to point to that modalScreenshots / GIFs
Before
Sheet will not present, will get warning in XCode.
After
Simulator.Screen.Recording.-.iPhone.17.Pro.Max.-.2025-11-23.at.21.47.34.mov
Test code and steps to reproduce
To test this change with a non-dismissible third-party modal (e.g., TrueSheet):
1. First, ensure your third-party modal implements the protocol (library author's responsibility):
2. Then test with this example:
RNSDismissibleModalProtocol)Checklist