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

SwiftUI中NavigationLink选中错误列表项且跳转报错问题咨询

问题复现

我正在实现一个简单的导航功能,需求是点击列表中的条目跳转后,可从弹出的sheet视图直接返回根控制器。实际运行出现两个异常:

  • 点击列表中的某一项时,加载的是错误的条目,点击的行和实际被高亮、加载的行之间存在偏移
  • 控制台输出报错:SwiftUI encountered an issue when pushing aNavigationLink. Please file a bug.

问题复现效果

问题原因

核心是两处逻辑错误导致导航系统混乱:

  1. 所有列表项的NavigationLink共用了同一个rootIsActive绑定作为激活状态,SwiftUI无法判断点击时要激活哪一行对应的导航链接,因此出现跳转偏移、报错的问题
  2. AllProjectView中的rootIsActive被声明为独立的@State变量,没有和ContentView传入的根状态绑定,导致返回根控制器的链路不通

修复方案

只需要修改两处代码即可:

  1. 将AllProjectView中的rootIsActive从@State改为@Binding,和父视图状态同步
  2. 移除ProjectItem中NavigationLink的isActive参数,该绑定属于多余逻辑,完全不需要

修复后完整代码

import SwiftUI

struct ContentView: View {
    @State var rootIsActive:Bool = false
    
    var body: some View {
        NavigationView{
            AllProjectView(rootIsActive: self.$rootIsActive)
        }
        .navigationBarTitle("Root")
        .navigationViewStyle(StackNavigationViewStyle())
        .environment(\.rootPresentationMode, self.$rootIsActive)
    }
}

struct AllProjectView: View {
    // 改为@Binding和父视图同步状态
    @Binding var rootIsActive:Bool
    @State var projects: [String] = ["1", "2", "3"]
    
    var body: some View{
        List{
            ForEach(projects.indices, id: \.self){ idx in
                ProjectItem(name: self.$projects[idx], rootIsActive: self.$rootIsActive)
            }
        }.navigationBarTitle("All Projects")
    }
}


struct ProjectItem: View{
    @Binding var name: String
    @Binding var rootIsActive: Bool
    
    init(name: Binding<String>, rootIsActive: Binding<Bool>){
        self._name = name
        self._rootIsActive = rootIsActive
    }
    
    var body: some View{
        // 移除多余的isActive绑定
        NavigationLink(
            destination: ProjectView(name: self.name)){
            Text(name)
        }
        .isDetailLink(false)
        .padding()
    }
}

struct ProjectView: View {
    var name: String
    @State var isShowingSheet: Bool = false
    @Environment(\.presentationMode) private var presentationMode: Binding<PresentationMode>
    @Environment(\.rootPresentationMode) private var rootPresentationMode: Binding<RootPresentationMode>
    
    var body: some View{
        VStack{
            Text(name)
            Button("Show Sheet"){
                self.isShowingSheet = true
            }
        }
        .sheet(isPresented: $isShowingSheet){
            Button("return to root"){
                self.isShowingSheet = false
                self.presentationMode.wrappedValue.dismiss()
                self.rootPresentationMode.wrappedValue.dismiss()
            }
        }
        .navigationBarTitle("Project View")
    }
}

struct RootPresentationModeKey: EnvironmentKey {
    static let defaultValue: Binding<RootPresentationMode> = .constant(RootPresentationMode())
}

extension EnvironmentValues {
    var rootPresentationMode: Binding<RootPresentationMode> {
        get { return self[RootPresentationModeKey.self] }
        set { self[RootPresentationModeKey.self] = newValue }
    }
}

typealias RootPresentationMode = Bool

extension RootPresentationMode {
    public mutating func dismiss() {
        self.toggle()
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 16:06:06