fix(ios): render dim in presenter view when presenter VC is detached#662
fix(ios): render dim in presenter view when presenter VC is detached#662kanzelm3 wants to merge 1 commit intolodev09:mainfrom
Conversation
|
@kanzelm3 is attempting to deploy a commit to the Dinky Team on Vercel. A member of the Team first needs to authorize it. |
71f3a1c to
8b6ff91
Compare
When TrueSheet is presented from a UIViewController that is not reachable from the key window's root VC via the parent/presentingViewController chain, UIKit's built-in UISheetPresentationController dim layer lands in the wrong UIWindow — the sheet content renders correctly but the dim appears in a fallback container instead of behind the sheet. iOS surfaces this at runtime as: "Presenting view controller ... from detached view controller ... is not supported, and may result in incorrect safe area insets and a corrupt root presentation." Detachment is inherited up the chain: a VC can have a non-nil presentingViewController but still be detached if that presenter is itself detached. A single-level check is not sufficient. Two changes: 1. findPresentingViewController walks superview.nextResponder to locate the nearest ancestor VC. This correctly finds VCs parked in the view tree by custom navigators (which may use addSubview: rather than modal presentation), where the previous window.rootViewController presentedViewController chain walk would miss them. 2. Added isPresenterDetached: which walks parent/presenting chain until it reaches the window's root VC. When the presenter is detached AND dimmed is YES, we add a fallback dim UIView as a subview of the presenter's view so it lives in the correct window below the natively-presented sheet. The dim is removed (animated) in dismissAnimated:, viewControllerWillDismiss, prepareForRecycle, and dealloc so every dismissal path — including swipe-dismiss and Fabric view recycling — cleans up correctly. No behavior change for the attached-presenter path. Closes lodev09#661
8b6ff91 to
501966f
Compare
|
I think I’m having a similar issue! I'm using true-sheet with true-tabs as the footer on my main home screen, then i navigate other screens in the main react-navigation (latest v7) tabs, then when i try to navigate back to home, it says |
|
I'm not sure about this. I'm trying to avoid functionalities that aren't supported natively, unless it's a real bug/issue. I believe you could also just render a custom backdrop yourself and even integrate reanimated to control the dim. |
I understand that, but you implemented a workaround for the sheet presenting below a modal... so not sure why you wouldn't also ensure that dimmed works in that case too. I banged my head against this for hours and realized it was a bug in the library. |
Yeah plenty of hacks on android just to make it consistent with IOS. What I'm avoiding is hacking IOS since things don't usually work correctly. Android is not very opinionated so you can do whatever you want. On your case, if you could make it work like the normal dim behavior then I'm good with it. Otherwise, I'll just treat it as limitation (which this library has plenty of). |
|
Did you try using custom dim backdrop yourself in JS side? |
I did but ran into timing issues with the fade in/out, will give it another go using the reanimated integration. |
Summary
Fixes #661.
On iOS, when a
TrueSheetis presented from aUIViewControllerthat is not reachable from the key window's root VC via theparent/presentingViewControllerchain (i.e. "detached" in UIKit's terms), the sheet content itself renders correctly, but UIKit'sUISheetPresentationControllerdim layer ends up in the wrongUIWindow. iOS surfaces this at runtime with:Two changes, both in
ios/TrueSheetView.mm:findPresentingViewControllerwalks the responder chain to locate the nearest ancestor VC. This correctly finds VCs parked in the view tree by custom navigators (which may useaddSubview:rather than modal presentation), where the previouswindow.rootViewController.presentedViewControllerchain walk would miss them and fall back to the app root.New
isPresenterDetached:helper walks theparent→presentingchain and only returns NO if it reaches the window's root VC. Detachment is inherited — a VC can have a non-nilpresentingViewControllerbut still be detached because that presenter is itself detached, so a single-level check is not sufficient. When the presenter is detached ANDdimmedis YES, a fallback dimUIViewis added as a subview of the presenter's view so it lives in the correct window below the natively-presented sheet. The dim is removed (animated) indismissAnimated:,viewControllerWillDismiss,prepareForRecycle, anddeallocso every dismissal path — including swipe-dismiss and Fabric view recycling — cleans up correctly.No behavior change for the attached-presenter path.
Type of Change
Test Plan
<Modal>inside aUIPageViewController-backed tree, TrueSheet inside the Modal). Confirmed the dim now renders correctly covering the Modal content and the sheet animates in/out as expected.isPresenterDetached:returnsNOand no fallback dim is added; UIKit's native dim continues to work exactly as before.yarn tidy✅yarn test✅ (43 passed)Screenshots / Videos
Before (dim lands in wrong window, behind the
<Modal>content):[happy to add a short screen recording from the repro app if helpful — let me know]
After (dim correctly covers the presenter's view):
[ditto]
Checklist
Notes for reviewer
dimmedDetentIndex: 0semantics, which is the common case). If you'd like it to respectdimmedDetentIndex > 0and fade with detent changes, happy to follow up — want to keep this PR focused for easier review.rgba(0, 0, 0, 0.4)— close to UIKit's default. Open to changing if there's a preferred value.