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

SwiftUI如何在同结构体中结合@FetchRequest与@ObservedObject实时更新UI

解决方案

1. 无需拆分父子视图的实现方式

你不需要单独拆分出子视图,只要在ForEach的遍历闭包中,把遍历到的Core Data实体对象声明为@ObservedObject即可,SwiftUI 5.3及以上版本都支持闭包参数加属性包装器,修改后的代码如下:

struct MainView: View {
    @Environment(\.managedObjectContext) private var moc
    @FetchRequest(entity: CDUser.entity(), sortDescriptors: [])
    var users: FetchedResults<CDUser>

    var body: some View {
        List {
            // 直接在闭包参数前加@ObservedObject监听单个实体变更
            ForEach(users, id: \.self) { @ObservedObject item in 
                Button(action: {
                    item.count = item.count + 1
                    do {
                        try moc.save()
                    } catch {
                        print(error)
                    }
                }, label: {
                    Text(String(item.count))
                })
            }
        }
    }
}

这样修改后,点击按钮修改实体属性时,@ObservedObject会直接触发当前视图刷新,不需要等页面重新出现。


2. 分组不自动更新的问题修复

你补充的分组场景不更新,核心原因是@FetchRequest的排序规则没有包含logged字段,当logged属性变更时,FetchRequest无法感知到该变更需要触发列表分组的重新计算,只需要给FetchRequest添加对应的排序器即可:

struct MainView: View {
    @Environment(\.managedObjectContext) private var moc
    // 给FetchRequest添加按logged字段排序的规则,logged变更时会自动重排结果
    @FetchRequest(entity: CDUser.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \CDUser.logged, ascending: false)])
    var users: FetchedResults<CDUser>
    
    var body: some View {
        List {
            Section(header: Text("Logged in")) {
                ForEach(users.filter({ $0.logged == true }), id: \.self) { @ObservedObject user in
                    Button(action: {
                        user.logged = false
                        do {
                            try moc.save()
                        } catch {
                            print(error)
                        }
                    }, label: {
                        Text(user.firstName ?? "")
                    })
                }
            }
            Section(header: Text("Logged out")) {
                ForEach(users.filter({ $0.logged == false }), id: \.self) { @ObservedObject user in
                    Button(action: {
                        user.logged = true
                        do {
                            try moc.save()
                        } catch {
                            print(error)
                        }
                    }, label: {
                        Text(user.firstName ?? "")
                    })
                }
            }
        }
    }
}

如果还需要额外的排序规则,比如按用户名排序,可以继续在sortDescriptors数组里追加对应的NSSortDescriptor即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 19:27:04