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

SwiftUI双列NavigationView旋转后无法加载详情页如何修复

问题描述

开发SwiftUI应用时使用了如下代码:

struct ContentView: View {
    var body: some View {
        NavigationView {
            Form {
                Section {
                    NavigationLink {
                        DetailsView()
                    } label: {
                        Text("Show details")
                    }
                }
            }
            Text("Select details")
        }
    }
}


struct DetailsView: View {
    
    @State var showModal = false
    
    var body: some View {
        ZStack {
            Color.gray.ignoresSafeArea()
            VStack {
                Spacer()
                Button {
                    showModal.toggle()
                } label: {
                    Text("Show modal")
                        .foregroundColor(.black)
                        .font(.system(size: 20, weight: .bold))
                }
            }
        }
        .fullScreenCover(isPresented: $showModal) {
            MyModalView {
                showModal = false
            }
        }
    }
}


struct MyModalView: View {
    
    
    var someAction:()->()
    
    var body: some View {
        ZStack {
            Color.black.ignoresSafeArea()
            Button {
                someAction()
            } label: {
                Text("some action")
                    .foregroundColor(.white)
            }
        }
    }
    
}

运行后出现异常:设备完成旋转操作后,点击「Show details」导航项无法正常展示DetailsView视图,异常效果如下:
异常效果演示

问题原因

该异常是旧版NavigationView的已知缺陷:NavigationView在宽屏场景下默认启用双列布局,设备旋转触发视图层级重算时,双列布局的导航选中状态会出现同步错误,导致导航点击事件无法正常响应,推入详情页的逻辑失效。

修复方案

可根据项目需求选择以下任意一种方案修复:

  • 方案1(最稳定,兼容所有iOS版本):强制导航栏使用栈式单例布局,完全规避双列布局的状态异常问题。
    仅需给NavigationView添加.navigationViewStyle(.stack)修饰符即可,修改后的ContentView代码如下:
    struct ContentView: View {
        var body: some View {
            NavigationView {
                Form {
                    Section {
                        NavigationLink {
                            DetailsView()
                        } label: {
                            Text("Show details")
                        }
                    }
                }
                Text("Select details")
            }
            .navigationViewStyle(.stack) // 新增该行强制使用栈导航样式
        }
    }
    
  • 方案2(需保留双列布局时使用):通过NavigationLink的选中绑定主动维护导航状态,替换硬编码的占位视图,避免旋转时状态丢失:
    struct ContentView: View {
        // 绑定当前导航选中项
        @State private var selectedItem: String? = nil
        
        var body: some View {
            NavigationView {
                Form {
                    Section {
                        NavigationLink(
                            "Show details",
                            tag: "details",
                            selection: $selectedItem
                        ) {
                            DetailsView()
                        }
                    }
                }
                // 无选中项时才展示占位视图
                if selectedItem == nil {
                    Text("Select details")
                }
            }
        }
    }
    

补充说明:如果项目最低支持iOS 16及以上版本,推荐直接使用苹果官方重构后的NavigationStack替换NavigationView,新组件从底层解决了绝大多数旧导航组件的状态同步问题,稳定性更高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 01:57:11