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
相关产品推荐
相关产品推荐

