You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI中DocumentGroup返回按钮误关Sheet而非关闭文档求助

问题解决思路:DocumentGroup返回按钮优先关闭Sheet的处理方案

核心问题:当DocumentGroup的文档页面弹出带有.presentationBackgroundInteraction(.enabled)的Sheet时,点击内置返回按钮只会关闭Sheet,不会触发文档的保存与关闭流程。以下是两种可行的解决方法:


方法一:替换内置返回按钮,自定义逻辑

由于navigationBarBackButtonHidden()对DocumentGroup的导航栏无效,我们通过UIKit方式隐藏默认按钮,再添加自定义按钮实现预期逻辑:

  1. 实现隐藏默认返回按钮的修饰器
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
        }
    }
}
  1. 修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 15:25:21