SwiftUI中NavigationLink选中错误列表项且跳转报错问题咨询
问题复现
我正在实现一个简单的导航功能,需求是点击列表中的条目跳转后,可从弹出的sheet视图直接返回根控制器。实际运行出现两个异常:
- 点击列表中的某一项时,加载的是错误的条目,点击的行和实际被高亮、加载的行之间存在偏移
- 控制台输出报错:
SwiftUI encountered an issue when pushing aNavigationLink. Please file a bug.

问题原因
核心是两处逻辑错误导致导航系统混乱:
- 所有列表项的
NavigationLink共用了同一个rootIsActive绑定作为激活状态,SwiftUI无法判断点击时要激活哪一行对应的导航链接,因此出现跳转偏移、报错的问题 AllProjectView中的rootIsActive被声明为独立的@State变量,没有和ContentView传入的根状态绑定,导致返回根控制器的链路不通
修复方案
只需要修改两处代码即可:
- 将
AllProjectView中的rootIsActive从@State改为@Binding,和父视图状态同步 - 移除
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
相关产品推荐
相关产品推荐

