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

SwiftUI侧边栏更新时导航状态重置问题求助

问题解决:Core Data添加数据后保持导航状态不重置

当你向Core Data添加新条目时,@FetchRequest会检测到数据变化并刷新ContentView的列表,旧的NavigationView会因为视图重绘丢失导航状态,导致回到根目录。以下是两种可行的解决方案:


方案一:iOS16+ 使用NavigationStack(推荐)

NavigationStack支持通过selection绑定主动维护导航状态,即使列表刷新也不会丢失选中状态。修改代码如下:

import SwiftUI
import CoreData

struct ContentView: View {
    @Environment(\.managedObjectContext) private var viewContext

    @FetchRequest(
        sortDescriptors: [NSSortDescriptor(keyPath: \Item.timestamp, ascending: true)],
        animation: .default)
    private var items: FetchedResults<Item>
    
    // 存储选中的Item的ID,维护导航状态
    @State private var selectedItemID: NSManagedObjectID?

    var body: some View {
        NavigationStack(selection: $selectedItemID) {
            List(selection: $selectedItemID) {
                NavigationLink("Add Item", value: nil) {
                    AddItemView()
                }
                ForEach(items) { item in
                    NavigationLink(value: item.objectID) {
                        Text(item.timestamp!, formatter: itemFormatter)
                    }
                }
            }
            // 根据选中ID显示对应详情
            if let selectedID = selectedItemID, let item = try? viewContext.existingObject(with: selectedID) as? Item {
                Text("Item at \(item.timestamp!, formatter: itemFormatter)")
            } else {
                Text("Select an item")
            }
        }
    }
}

// AddItemView、AddItemDetailView代码保持不变

方案二:兼容iOS15及以下

通过手动保存选中的Item的ID,在列表刷新后重新恢复选中状态:

import SwiftUI
import CoreData

struct ContentView: View {
    @Environment(\.managedObjectContext) private var viewContext

    @FetchRequest(
        sortDescriptors: [NSSortDescriptor(keyPath: \Item.timestamp, ascending: true)],
        animation: .default)
    private var items: FetchedResults<Item>
    
    @State private var selectedItemID: NSManagedObjectID?
    @State private var isAddItemActive = false

    var body: some View {
        NavigationView {
            List {
                // 单独管理Add Item的导航状态
                Button("Add Item") {
                    isAddItemActive = true
                }
                ForEach(items) { item in
                    NavigationLink(
                        destination: Text("Item at \(item.timestamp!, formatter: itemFormatter)"),
                        tag: item.objectID,
                        selection: $selectedItemID
                    ) {
                        Text(item.timestamp!, formatter: itemFormatter)
                    }
                }
            }
            .background(
                NavigationLink(isActive: $isAddItemActive) {
                    AddItemView()
                } label: {
                    EmptyView()
                }
            )
            Text("Select an item")
        }
    }
}

// AddItemView、AddItemDetailView代码保持不变

方案二中,把"Add Item"改成Button配合隐藏的NavigationLink,避免它和Item的导航链接共享状态;同时用tag和selection绑定维护选中的Item,即使列表刷新,selectedItemID会保留,导航状态也会恢复。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 03:13:22