SwiftUI中DocumentGroup返回按钮误关Sheet而非关闭文档求助
问题解决思路:DocumentGroup返回按钮优先关闭Sheet的处理方案
核心问题:当DocumentGroup的文档页面弹出带有.presentationBackgroundInteraction(.enabled)的Sheet时,点击内置返回按钮只会关闭Sheet,不会触发文档的保存与关闭流程。以下是两种可行的解决方法:
方法一:替换内置返回按钮,自定义逻辑
由于navigationBarBackButtonHidden()对DocumentGroup的导航栏无效,我们通过UIKit方式隐藏默认按钮,再添加自定义按钮实现预期逻辑:
- 实现隐藏默认返回按钮的修饰器
struct HideDefaultBackButton: UIViewControllerRepresentable { func makeUIViewController(context: Context) -> some UIViewController { UIViewController() } func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) { DispatchQueue.main.async { uiViewController.navigationController?.navigationBar.topItem?.hidesBackButton = true } } }
- 修改ContentView,绑定Sheet状态与自定义返回逻辑
struct ContentView: View { @State private var sheetIsPresented = true @Environment(\.dismiss) private var dismissDocument var body: some View { Text("Background") .background(HideDefaultBackButton()) .sheet(isPresented: $sheetIsPresented) { Text("Sheet") .presentationDetents([.medium]) .presentationBackgroundInteraction(.enabled(upThrough: .medium)) } .toolbar { ToolbarItem(placement: .navigationBarLeading) { Button("返回") { if sheetIsPresented { // 先关闭Sheet,延迟确保动画完成后触发文档关闭 sheetIsPresented = false DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { dismissDocument() } } else { dismissDocument() } } } } } }
方法二:拦截内置返回按钮的点击动作
如果不想替换按钮样式,可通过UIKit拦截返回按钮的点击事件,自定义处理逻辑:
struct ContentView: View { @State private var sheetIsPresented = true @Environment(\.dismiss) private var dismissDocument var body: some View { Text("Background") .sheet(isPresented: $sheetIsPresented) { Text("Sheet") .presentationDetents([.medium]) .presentationBackgroundInteraction(.enabled(upThrough: .medium)) } .onAppear { guard let navController = UIApplication.shared.windows.first?.rootViewController?.children.first as? UINavigationController else { return } // 替换返回按钮的触发动作 let customBackButton = UIBarButtonItem(title: "返回", style: .plain, target: self, action: #selector(handleBackTap)) navController.navigationBar.topItem?.backBarButtonItem = customBackButton } } @objc private func handleBackTap() { if sheetIsPresented { sheetIsPresented = false DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { dismissDocument() } } else { dismissDocument() } } }
关键注意点
- 必须将Sheet的
isPresented绑定到@State变量,不能使用.constant(true),否则无法控制和检测Sheet状态。 @Environment(\.dismiss)获取的dismissDocument()动作,会完全复现内置返回按钮的原生行为:触发文档保存并关闭当前文档页面。
内容的提问来源于stack exchange,提问作者Luïs
相关产品推荐
相关产品推荐

