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

SwiftUI中List内嵌GridItem时NavigationLink跳转错误问题求助

问题原因

这个是SwiftUI List组件的已知系统Bug,根源在于List底层依赖的UITableView复用机制,和你当前全局单NavigationLink的状态更新逻辑出现了时序冲突:你点击条目给viewRouter.selectedItem赋值后,List还在完成内部单元格的渲染流程,会把你刚设置的selectedItem值覆盖为当前网格最后一个完成渲染的条目,最终导致始终跳转到最后一项。

修复方案

方案1:修改NavigationLink绑定逻辑(推荐,无副作用)

废弃全局共用isActive的写法,改用NavigationLink的tag+selection绑定机制,把跳转逻辑和每个条目直接绑定,避免状态被覆盖。改动后的核心代码如下:

struct ItemsListView: View {
    
    @EnvironmentObject var viewRouter: ViewRouter
    // 可直接绑定到viewRouter的selectedItem,无需额外本地状态
    @State private var selectedItem: Item?

    @SectionedFetchRequest(
      sectionIdentifier: SortModel.default.section,
      sortDescriptors: SortModel.default.descriptors,
      animation: .default
    )
    private var coreData: SectionedFetchResults<String, Item>
    
    
    let layout = [GridItem(.adaptive(minimum: 100)),
                  GridItem(.adaptive(minimum: 100)),
                  GridItem(.adaptive(minimum: 100))]
    
    var body: some View {
        NavigationStack { // iOS15及以下替换为NavigationView
            List {
                ForEach(coreData) { section in
                  Section(header: Text(section.id)) {
                      LazyVGrid(columns: layout, spacing: 10) {
                          ForEach(section) { item in
                              NavigationLink(tag: item, selection: $selectedItem) {
                                  ItemDetailView(item: item)
                              } label: {
                                  LabelView(item: item)
                              }
                          }
                      }
                  }
                }
            }
        }
    }
}

注意需要确保Item实体遵循Hashable协议,CoreData自动生成的实体默认已符合要求。

方案2:最小改动临时规避

不想改动现有逻辑的话,只需要给选中项赋值的逻辑加个主队列异步包裹,等List的渲染流程走完再激活跳转,就能避免值被覆盖:

Button(action: {
    DispatchQueue.main.async {
        viewRouter.selectedItem = item
        viewRouter.detailActive = true
    }
}, label: {
    LabelView(item: item)
})

方案3:替换List为ScrollView

如果你的场景不需要List自带的侧滑删除、section吸顶、系统列表样式等特性,直接替换为ScrollView即可完全规避这个问题,和你测试的结果一致。

内容的提问来源于stack exchange,提问作者blu-Fox

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 00:45:06