SwiftUI中在View的body内存储耗时计算结果到局部变量是否合理?
问题结论
你的实现是符合SwiftUI渲染逻辑的合理优化方案,不存在数据不同步的问题,在对应场景下属于推荐的最佳实践之一。
原理解释
- SwiftUI的
body属性的执行是单次原子性的同步运算过程,只有当它依赖的可观测值(这里是@StateObject修饰的viewModel的@Published属性)发生变更时,才会触发整个body的重新计算。 - 你在
body顶部声明的局部变量num,会在本次body渲染周期内被所有引用它的子视图共用同一个值,既不会重复执行expensiveWork的计算逻辑,也不可能出现同一渲染周期内不同子视图拿到的num值不一致的情况。
适用场景和优化方向
- 如果你的昂贵计算仅在当前
View的body中使用,且同一个渲染周期内会被引用2次及以上,你当前的写法已经完全够用,没有任何副作用。 - 如果该计算的开销极高,或者计算结果需要在多个
View中复用,还可以选择把缓存逻辑下沉到ViewModel层,只有依赖的源值变更时才重新计算,进一步降低渲染时的开销:
class ViewModel: ObservableObject { @Published var num = 0 { didSet { // 仅当num变更时才重新计算,避免重复执行 cachedExpensiveWork = num * 20 } } private(set) var cachedExpensiveWork: Int = 0 func doWork() { num = Int.random(in: 0..<100) } }
对应的View中可以直接读取缓存值,不需要再在body中做临时存储:
var body: some View { Text("Number: \(viewModel.cachedExpensiveWork)") .contextMenu { Button("Press me \(viewModel.cachedExpensiveWork)") { viewModel.doWork() } } .frame(width: 150, height: 100) }
注意事项
如果你的昂贵计算依赖的属性不只是ViewModel的发布属性,还包含当前View的本地@State、@Binding等属性,那在body中声明局部变量存储计算结果就是最简便合理的方案,不需要额外做缓存处理。
内容的提问来源于stack exchange,提问作者user17576470
相关产品推荐
相关产品推荐

