diff --git a/Sources/BetterSafariView/SafariView/SafariViewPresenter.swift b/Sources/BetterSafariView/SafariView/SafariViewPresenter.swift index 255529c..bc61799 100644 --- a/Sources/BetterSafariView/SafariView/SafariViewPresenter.swift +++ b/Sources/BetterSafariView/SafariView/SafariViewPresenter.swift @@ -3,6 +3,10 @@ import SwiftUI import SafariServices +// `SafariViewPresenter` conforms `UIViewRepresentable` instead of `UIViewControllerRepresentable`. +// This fixes an issue where the Safari view controller is not presented properly +// when the `UIViewControllerRepresentable` is detached from the root view controller +// (e.g. `UIViewController` contained in `UITableViewCell`). struct SafariViewPresenter: UIViewRepresentable { // MARK: Representation @@ -80,30 +84,20 @@ extension SafariViewPresenter { safariViewController.delegate = self representation.applyModification(to: safariViewController) - if #available(iOS 17.0, *) { - if var topController = UIApplication.shared.windows.filter(\.isKeyWindow).first?.rootViewController { - while let presentedViewController = topController.presentedViewController { - topController = presentedViewController - } - topController.present(safariViewController, animated: true, completion: nil) - } - self.safariViewController = safariViewController + // Presents a Safari view controller from the farthest `presentedViewController` of `UIWindow`. + // (same approach when presenting `UIAlertController`) + guard let presentingViewController = uiView.window?.farthestPresentedViewController else { + assertionFailure( + "Cannot find the view controller to present from." + + " This happens when a 'SafariViewPresenter' is detached from the window, or the window doesn't have 'rootViewController.'" + ) + self.resetItemBinding() return - } else { - // Present a Safari view controller from the `viewController` of `UIViewRepresentable`, instead of `UIViewControllerRepresentable`. - // This fixes an issue where the Safari view controller is not presented properly - // when the `UIViewControllerRepresentable` is detached from the root view controller (e.g. `UIViewController` contained in `UITableViewCell`) - // while allowing it to be presented even on the modal sheets. - // Thanks to: Bohdan Hernandez Navia (@boherna) - guard let presentingViewController = uiView.viewController else { - self.resetItemBinding() - return - } - - presentingViewController.present(safariViewController, animated: true) - - self.safariViewController = safariViewController } + + presentingViewController.present(safariViewController, animated: true) + + self.safariViewController = safariViewController } private func updateSafariViewController(with item: Item) {