SwiftUI中NavigationLink跳转的SFSafariViewController Done按钮可点击区域过小问题
问题描述
通过程序化NavigationLink集成SFSafariViewController时,Done按钮仅“ne”部分特定角度可点击;改用sheet模态展示时按钮功能正常,但需保留NavigationLink跳转方式。
解决方案
方案1:使用NavigationPath替代isActive式导航
改用NavigationStack+NavigationPath管理导航,规避旧版isActive导航可能引发的层级冲突:
// HomeView 实现 struct HomeView: View { @State private var navigationPath = NavigationPath() var body: some View { NavigationStack(path: $navigationPath) { VStack(spacing: 0) { Spacer() Button("Show Website") { navigationPath.append(URL(string: "https://www.example.com")!) } Spacer() } .navigationDestination(for: URL.self) { url in SafariView(url: url) .navigationBarHidden(true) } } } } // SafariView 保留原实现不变
方案2:通过绑定状态同步导航激活状态
移除@Environment(\.dismiss),改用绑定状态控制导航激活,避免环境 Dismiss 与SFSafariVC原生按钮的交互冲突:
// 修改后的SafariView struct SafariView: UIViewControllerRepresentable { @Binding var isActive: Bool let url: URL func makeUIViewController(context: Context) -> SFSafariViewController { let vc = SFSafariViewController(url: url) vc.preferredControlTintColor = .tintColor vc.delegate = context.coordinator return vc } func updateUIViewController(_ vc: SFSafariViewController, context: Context) {} class Coordinator: NSObject, SFSafariViewControllerDelegate { private let isActive: Binding<Bool> init(isActive: Binding<Bool>) { self.isActive = isActive } func safariViewControllerDidFinish(_ controller: SFSafariViewController) { isActive.wrappedValue = false } } func makeCoordinator() -> Coordinator { Coordinator(isActive: $isActive) } } // 修改后的HomeView struct HomeView: View { @State private var isBtnActive: Bool = false var body: some View { NavigationStack { NavigationLink( destination: SafariView(isActive: $isBtnActive, url: URL(string: "https://www.example.com")!) .navigationBarHidden(true), isActive: $isBtnActive, label: { EmptyView() } ) .accessibilityHidden(true) VStack(spacing: 0) { Spacer() Button("Show Website") { isBtnActive = true } Spacer() } } } }
方案3:添加安全区域忽略
让SafariView完全占据导航栈视图空间,避免SwiftUI布局元素遮挡按钮:
// 修改HomeView中的NavigationLink部分 NavigationLink( destination: SafariView(url: URL(string: "https://www.example.com")!) .edgesIgnoringSafeArea(.all) .navigationBarHidden(true), isActive: $isBtnActive, label: { EmptyView() } )
问题根源
SwiftUI导航栈与SFSafariViewController的导航栏存在层级或布局冲突,导致Done按钮部分区域被SwiftUI的透明布局元素遮挡。上述方案从导航管理、状态同步、布局占比三个维度解决该冲突。
内容的提问来源于stack exchange,提问作者kittonian
相关产品推荐
相关产品推荐

