SwiftUI中如何在init()中遍历@FetchRequest的FetchedResults?
解决SwiftUI中@FetchRequest在init内遍历的问题
问题原因
_allItems是@FetchRequest的投影属性,类型为FetchRequest<Item>而非实际的查询结果FetchedResults<Item>,因此无法直接调用forEach。- 更核心的问题:View的
init执行时,@FetchRequest尚未完成数据加载——SwiftUI会在View插入视图树、绑定到环境中的managedObjectContext后,才会执行Core Data查询并填充allItems,所以init阶段根本拿不到有效数据。
正确实现方式
方式1:视图出现时处理数据
用onAppear modifier,在View首次渲染完成后遍历查询结果:
struct MyView: View { @FetchRequest( sortDescriptors: [SortDescriptor(\.title)] )var allItems: FetchedResults<Item> var body: some View { // 替换为你的视图内容 Text("物品数量:\(allItems.count)") .onAppear { allItems.forEach { item in performFunction(item: item) } } } func performFunction(item: Item) { // 写入你的处理逻辑 } }
方式2:监听数据变化(更新时自动触发)
如果需要在allItems数据变更时也执行操作,使用onChange(of:):
struct MyView: View { @FetchRequest( sortDescriptors: [SortDescriptor(\.title)] )var allItems: FetchedResults<Item> var body: some View { Text("物品数量:\(allItems.count)") .onChange(of: allItems) { newItems in newItems.forEach { item in performFunction(item: item) } } } func performFunction(item: Item) { // 写入你的处理逻辑 } }
方式3:直接用Core Data上下文查询(适合初始化必须处理的场景)
如果必须在初始化阶段获取数据,跳过@FetchRequest,直接通过上下文执行查询:
struct MyView: View { let allItems: [Item] init(context: NSManagedObjectContext) { let fetchRequest: NSFetchRequest<Item> = Item.fetchRequest() fetchRequest.sortDescriptors = [SortDescriptor(\.title)] do { allItems = try context.fetch(fetchRequest) allItems.forEach { item in performFunction(item: item) } } catch { // 处理查询错误 allItems = [] print("查询失败:\(error)") } } var body: some View { Text("物品数量:\(allItems.count)") } func performFunction(item: Item) { // 写入你的处理逻辑 } } // 使用时传入上下文 // MyView(context: viewContext)
注意事项
@FetchRequest是为SwiftUI响应式更新设计的,优先使用前两种方式,可自动监听数据变化并刷新视图。- 直接查询上下文的方式不具备自动更新能力,数据变化后需手动处理视图刷新。
内容的提问来源于stack exchange,提问作者KingFish
相关产品推荐
相关产品推荐

