SwiftUI 如何从Core Data中获取打乱顺序的数组并在视图中渲染
问题根源
你最初的写法渲染空视图,核心原因是在View的init方法中访问FetchRequest的wrappedValue时机过早:View的init仅用于构建SwiftUI视图树结构,此时Core Data还未执行实际的查询操作,拿到的是未加载的空数组,赋值给属性后就不会再自动更新。
第三种写法动画失效,是因为task修饰符为异步执行,数据赋值和视图渲染不同步,且没有显式包裹动画逻辑,导致过渡效果丢失。
最优解决方案
方案1:无需额外存储,直接动态打乱
如果你接受每次视图重绘、Core Data数据更新时都自动重新打乱顺序,直接在body中处理即可,代码最简洁:
struct ChildView: View { // 注意要加@FetchRequest属性包装器,才能自动监听Core Data数据更新 @FetchRequest( entity: Entity.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \Entity.name, ascending: true)] ) private var entityData: FetchedResults<Entity> var body: some View { VStack { ForEach(entityData.shuffled()) { entity in Text(entity.name ?? "") } } } }
方案2:固定打乱顺序,保留动画效果
如果你希望打乱后的顺序在视图生命周期内固定、仅在Core Data数据更新或视图重新进入时才刷新,同时保证动画正常,用以下写法:
struct ChildView: View { @FetchRequest( entity: Entity.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \Entity.name, ascending: true)] ) private var entityData: FetchedResults<Entity> @State private var shuffledEntities: [Entity] = [] var body: some View { VStack { ForEach(shuffledEntities) { entity in Text(entity.name ?? "") } } .onAppear { // 视图首次出现时打乱,显式包裹动画 withAnimation { shuffledEntities = entityData.shuffled() } } .onChange(of: entityData) { newData in // 监听Core Data数据变化,自动更新打乱后的数组 withAnimation { shuffledEntities = newData.shuffled() } } // 如果需要每次进入视图都重新打乱,加上下面这行 .onDisappear { shuffledEntities = [] } } }
这个方案完全由子视图自行管理数据拉取、打乱逻辑,不需要父视图参与,同时解决了动画失效的问题。
内容的提问来源于stack exchange,提问作者blu-Fox
相关产品推荐
相关产品推荐

