如何在SwiftUI中避免SwiftData @Query计算属性重复计算
解决SwiftUI中分组计算重复执行的问题
针对你遇到的@Query数据变化时分组计算重复执行的问题,有两种靠谱的解决方式,适配不同iOS版本:
方法一:iOS 17+ 用@Memoized宏(最简单)
苹果在iOS17新增了@Memoized宏,专门用来缓存计算属性的结果,只有当它依赖的数据源变化时才会重新计算。直接给你的grouped属性加上这个宏就行:
struct GroupListView: View { @Query var persons: [Person] @Memoized var grouped: [[Person]] { // 你的耗时分组操作 } var body: some View { VStack { Text("There are \(grouped.count) groups") List { ForEach(grouped, id: \.self) { group in Text("Number of members: \(group.count)") } } } } }
这样不管grouped在body里被调用多少次,只要persons没变化,就只会用缓存的结果,不会重复执行分组逻辑。
方法二:iOS 17以下 用ViewModel监听数据变化
如果需要兼容iOS17之前的版本,可以用ObservableObject做一个视图模型,在里面监听persons的变化,只在数据更新时重新计算分组:
class GroupListViewModel: ObservableObject { @Published var grouped: [[Person]] = [] func updateGrouped(with persons: [Person]) { // 你的耗时分组操作,赋值给grouped grouped = // 分组逻辑 } } struct GroupListView: View { @Query var persons: [Person] @StateObject private var viewModel = GroupListViewModel() var body: some View { VStack { Text("There are \(viewModel.grouped.count) groups") List { ForEach(viewModel.grouped, id: \.self) { group in Text("Number of members: \(group.count)") } } } .onChange(of: persons) { newPersons in viewModel.updateGrouped(with: newPersons) } .onAppear { // 首次加载时初始化分组 viewModel.updateGrouped(with: persons) } } }
这个方法里,只有当persons发生变化时,才会调用updateGrouped方法重新计算,视图其他状态变化不会触发重复计算。
另外注意:你的ForEach需要添加id: \.self,因为[Person]数组默认不遵循Identifiable协议,否则会编译报错。
内容的提问来源于stack exchange,提问作者Mink96
相关产品推荐
相关产品推荐

