diff --git a/ios/TrueSheetView.swift b/ios/TrueSheetView.swift index 647d8332..46ab56f6 100644 --- a/ios/TrueSheetView.swift +++ b/ios/TrueSheetView.swift @@ -418,50 +418,65 @@ class TrueSheetView: UIView, RCTInvalidating, TrueSheetViewControllerDelegate { promise.resolve(nil) } } + + private func topPresenter() -> UIViewController? { + reactViewController()?.topMostPresenter + } - func present(at index: Int, promise: Promise?, animated: Bool = true) { - let rvc = reactViewController() + func present(at index: Int, promise: Promise?, animated: Bool = true) { + guard let presenter = topPresenter() else { + promise?.reject(message: "No react view controller present.") + return + } - guard let rvc else { - promise?.reject(message: "No react view controller present.") - return - } + guard viewController.sizes.indices.contains(index) else { + promise?.reject(message: "Size at \(index) is not configured.") + return + } - guard viewController.sizes.indices.contains(index) else { - promise?.reject(message: "Size at \(index) is not configured.") - return - } + if isPresented { + if #available(iOS 15.0, *) { + withPresentedSheet { sheet in + sheet.selectedDetentIdentifier = viewController.detentIdentifierForIndex(index) + viewControllerDidChangeSize(self.viewController.currentSizeInfo) + promise?.resolve(nil) + } + } else { + viewControllerDidChangeSize(viewController.currentSizeInfo) + promise?.resolve(nil) + } + return + } + + viewController.prepareForPresentation(at: index) { [weak self] in + guard let self = self else { return } - if isPresented { - if #available(iOS 15.0, *) { - withPresentedSheet { sheet in - sheet.selectedDetentIdentifier = viewController.detentIdentifierForIndex(index) + self.activeIndex = index + self.isPresented = true - // Trigger onSizeChange event when size is changed while presenting - viewControllerDidChangeSize(self.viewController.currentSizeInfo) - promise?.resolve(nil) + presenter.present(self.viewController, animated: animated) { + if #available(iOS 15.0, *) { + self.viewController.observeDrag() + } + + let data = self.sizeInfoData(from: self.viewController.currentSizeInfo) + self.dispatchEvent(name: "onPresent", block: self.onPresent, data: data) + promise?.resolve(nil) + } } - } else { - // Trigger onSizeChange event when size is changed while presenting - viewControllerDidChangeSize(viewController.currentSizeInfo) - promise?.resolve(nil) - } - } else { - viewController.prepareForPresentation(at: index) { - // Keep track of the active index - self.activeIndex = index - self.isPresented = true - - rvc.present(self.viewController, animated: animated) { - if #available(iOS 15.0, *) { - self.viewController.observeDrag() - } - - let data = self.sizeInfoData(from: self.viewController.currentSizeInfo) - self.dispatchEvent(name: "onPresent", block: self.onPresent, data: data) - promise?.resolve(nil) + } +} + +extension UIViewController { + /// Returns the view controller that should receive a new modal presentation. + /// Walks the hierarchy: RN root → UINavigationController → presented VCs. + var topMostPresenter: UIViewController { + var top = self + while let presented = top.presentedViewController { + top = presented } - } + // If we are inside a UINavigationController, present from the navigation controller + // so the sheet appears over the whole navigation stack. + return top.navigationController ?? top } - } }