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

SwiftUI问题:关闭ActionSheet/sheet时父视图FooView意外弹出

问题解决:关闭ActionSheet时FooView意外从导航栈弹出

触发原因

  • 在iOS 15的SwiftUI中,NavigationView嵌套TabView的层级结构会引发状态管理冲突。当ActionSheet的isPresented状态从true切换回false时,视图层级的状态刷新会错误传递至NavigationView的导航栈,触发NavigationLink的自动取消逻辑,最终导致FooView被弹出。
  • 该问题属于SwiftUI在特定嵌套结构下的状态同步Bug,在iOS 16及后续版本中已被官方修复。

解决方案

方案一:调整视图层级(推荐,符合SwiftUI最佳实践)

将TabView移至NavigationView外部,让每个标签页对应独立的导航栈,隔离状态避免干扰:

@main
struct ViewDismissApp: App {
    var body: some Scene {
        WindowGroup {
            TabView {
                NavigationView {
                    ContentView(title: "Tab 1")
                }
                .navigationViewStyle(.stack)
                .tabItem {
                    Label("Tab1", systemImage: "wifi")
                }
                
                NavigationView {
                    ContentView(title: "Tab 2")
                }
                .navigationViewStyle(.stack)
                .tabItem {
                    Label("Tab2", systemImage: "wrench.adjustable")
                }
            }
        }
    }
}

方案二:手动控制导航栈状态

通过NavigationLink的isActive绑定手动管理导航状态,避免自动触发的弹出逻辑:

  1. 修改ContentView:
struct ContentView: View {
    let title: String
    @State private var isNavigating = false

    var body: some View {
        VStack {
            Button(title) {
                isNavigating = true
            }
            .background(
                NavigationLink(destination: FooView(isActive: $isNavigating), isActive: $isNavigating) {
                    EmptyView()
                }
            )
        }
    }
}
  1. 修改FooView:
struct FooView: View {
    @Binding var isActive: Bool
    @State private var showActions = false

    var body: some View {
        VStack {
            Text("Foo View")
            actionButton()
        }
        .navigationBarBackButtonHidden(true)
        .toolbar {
            ToolbarItem(placement: .navigationBarLeading) {
                Button("返回") {
                    isActive = false
                }
            }
        }
    }
    
    private func actionButton() -> some View {
        Button(action: {
            showActions = true
        }) {
            Image(systemName: "arrow.up.circle")
        }
        .actionSheet(isPresented: $showActions) {
            ActionSheet(title: Text("Actions"),
                        message: nil,
                        buttons: [
                            .default(Text("Option 1")) {
                                // TODO
                            },
                            .default(Text("Option 2")) {
                                // TODO
                            },
                            .cancel()
                        ])
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 01:35:19