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

Swift Core Data状态管理问题:编辑Item后ItemsView不更新

问题根源

你猜的没错,问题确实出在两个ForEach的数据源上:

  • CategoriesView使用的FetchedResults<Category>是Core Data提供的自动监听数据变化的集合类型,任何Category的属性或关联数据变化时,都会自动触发视图更新。
  • ItemsView里的categoryItems是从Category的items(NSSet)转换来的普通数组,这个数组不会主动发布数据变化通知;同时,ForEach遍历普通数组时,即使单个Item的属性被修改,SwiftUI也无法感知到变化——因为数组本身的元素引用没改变,且没有监听Item对象的属性更新。
解决方法

推荐两种靠谱的修复方式,选其一即可:

方法1:改用FetchRequest获取当前分类下的Item

把ItemsView的数据源换成针对当前Category的FetchRequest,利用Core Data的自动监听能力:

struct ItemsView: View {
    @ObservedObject var category: Category
    @State private var isEditingItem = false
    
    // 新增针对当前Category的FetchRequest
    @FetchRequest var items: FetchedResults<Item>
    
    init(category: Category) {
        _items = FetchRequest(
            sortDescriptors: [SortDescriptor(\.name)],
            predicate: NSPredicate(format: "category == %@", category)
        )
        self.category = category
    }
    
    var body: some View {
        VStack {
            List {
                // 遍历FetchResults<Item>
                ForEach(items) { item in
                    NavigationLink {
                        // 保留原有逻辑
                    } label: {
                        Text(item.itemName)
                    }
                    .contextMenu {
                        Button {
                            isEditingItem.toggle()
                        } label: {
                            Label("Edit Item", systemImage: "pencil")
                        }
                    }
                    .sheet(isPresented: $isEditingItem) {
                        EditItemView(item: item)
                    }
                }
            }
        }
        .navigationTitle(category.categoryName)
    }
}

方法2:让Category的关联Item集合支持SwiftUI监听

修改Category的扩展,给关联集合添加变化通知触发逻辑,同时让ForEach能跟踪单个Item的变化:

extension Category {
    var categoryName: String {
        name ?? "New Category"
    }
    
    var categoryItems: [Item] {
        get {
            items?.allObjects as? [Item] ?? []
        }
    }
}

然后修改ItemsView中的ForEach,添加id: \.objectID(Core Data对象的objectID是唯一且稳定的标识):

ForEach(category.categoryItems, id: \.objectID) { item in
    // 原有视图代码
}

这样当Item的属性变化时,SwiftUI能通过objectID识别到元素更新,触发视图刷新。

额外优化建议
  • EditItemView中的item建议改为@ObservedObject var item: Item,这样在编辑过程中如果有其他地方修改了该Item,视图也能实时更新:
struct EditItemView: View {
    @ObservedObject var item: Item
    // 其他代码不变
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 18:24:26