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

SwiftUI如何判断当前视图是否通过sheet方式呈现?

问题原因

你当前的写法不生效是因为 presentationMode.wrappedValue.isPresented 的判定逻辑为「只要当前视图不是根视图,被其他视图推入/呈现时就会返回true」,无论是NavigationLink推入还是sheet弹出都会命中该条件,所以两个场景都会展示Banner。

解决方案

方案1:自定义属性注入(最推荐,全iOS版本兼容)

这是逻辑最可控、无兼容风险、实现成本最低的方案,直接给LoginView新增一个标识属性即可:

struct LoginView: View {
    /// 标记当前视图是否以sheet形式弹出
    let isPresentedAsSheet: Bool
    
    var body: some View {
        if isPresentedAsSheet {
            Banner()
        }
        // 剩余原有视图逻辑
    }
}

不同场景调用时传入对应的值:

// NavigationLink 场景传入false
NavigationLink(destination: LoginView(isPresentedAsSheet: false)) {
  Text("To login")
}
// sheet 场景传入true
.sheet(isPresented: $viewModel.isShowingSheet) {
    LoginView(isPresentedAsSheet: true)
}

后续如果新增其他模态呈现方式(比如fullScreenCover)也可以灵活扩展标识,不会出现系统版本适配问题。

方案2:自动判定呈现类型(iOS15+可用,不推荐)

如果不想手动传参,可以利用SwiftUI内部环境变量的类型差异做判定,但该方案依赖系统内部实现,后续苹果修改实现逻辑可能失效:

struct LoginView: View {
    @Environment(\.dismiss) private var dismiss
    
    private var isPresentedAsSheet: Bool {
        // sheet弹出的dismiss为PresentationAction类型,导航栈推入的为NavigationDismissAction类型
        String(describing: dismiss).contains("PresentationAction")
    }
    
    var body: some View {
        if isPresentedAsSheet {
            Banner()
        }
        // 剩余原有视图逻辑
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.11 14:51:02