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

如何在iOS 15及更早版本中支持SwiftUI程序化关闭视图

问题根源

@Environment 是视图层级的属性声明,编译期就会确定布局,不能放在运行时执行的 if #available 条件块中,因此你之前的条件声明写法本身不符合语法规则。

解决方案

方案1:最简兼容写法(推荐)

直接同时声明两个环境变量,iOS 14 及更低版本会自动忽略不存在的 \dismiss 环境变量,不会产生运行时问题,调用时按系统版本区分即可,同时完美避开 iOS 15 下 presentationMode 在 NavigationView 嵌套 TabView 场景下的失效 bug:

// 视图属性区直接同时声明两个环境变量
@Environment(\.presentationMode) var presentationMode
@Environment(\.dismiss) var dismiss

// 调用关闭逻辑时做版本判断
func closeView() {
    if #available(iOS 15, *) {
        dismiss()
    } else {
        presentationMode.wrappedValue.dismiss()
    }
}

你提供的问题场景中,只要把 ChildView 按上面的写法修改,即可正常执行关闭操作。

方案2:全局封装(可选)

如果不想每个视图都重复声明两个环境变量,可以封装成自定义的全局关闭方法:

// 先定义自定义环境键
struct DismissAction: EnvironmentKey {
    static let defaultValue: () -> Void = {}
}

extension EnvironmentValues {
    var autoDismiss: () -> Void {
        get { self[DismissAction.self] }
        set { self[DismissAction.self] = newValue }
    }
}

// 在App入口或者根视图注入实现
@main
struct YourApp: App {
    @Environment(\.dismiss) var dismiss
    @Environment(\.presentationMode) var presentationMode
    
    var body: some Scene {
        WindowGroup {
            RootView()
                .environment(\.autoDismiss, {
                    if #available(iOS 15, *) {
                        dismiss()
                    } else {
                        presentationMode.wrappedValue.dismiss()
                    }
                })
        }
    }
}

// 后续所有子视图直接调用即可
struct ChildView: View {
    @Environment(\.autoDismiss) var autoDismiss
    
    var body: some View {
        Button("POP") {
            autoDismiss()
        }
    }
}

内容的提问来源于stack exchange,提问作者mota

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.10 04:09:02