SwiftUI中含类数组的@Observable类滑动时内存占用过高问题
问题根源
@Observable类的特性是:当类中任意属性发生变化时,整个对象会被标记为已变更,触发所有依赖该对象的视图重绘。在你的代码中,滑动滑块修改variable时,整个ObserveThis实例都会触发更新,导致展示数组的LazyVGrid部分也随之频繁重绘;加上数组中存储的是类实例,频繁的视图重建会导致内存占用持续攀升。
解决办法
1. 拆分Observable对象,隔离可变属性与静态数组
将需要频繁更新的滑块变量和静态数组拆分到两个独立的@Observable类中,这样当滑块变量变化时,只有依赖它的视图会更新,数组相关视图不受影响:
class Thing: Identifiable { let id = UUID() var variable: UInt8 = 0 init(variable: UInt8 = 0) { self.variable = variable } } @Observable class SliderState { var variable: Float = 1 } @Observable class ThingState { var things = [[Thing]](repeating: [Thing](repeating: Thing(), count: 512), count: 8) } struct ContentView: View { @State private var sliderState = SliderState() @State private var thingState = ThingState() private let flexibleColumn = [ GridItem(.flexible(minimum: 100, maximum: 200)), GridItem(.flexible(minimum: 100, maximum: 200)), GridItem(.flexible(minimum: 100, maximum: 200)) ] var body: some View { VStack { Slider( value: $sliderState.variable, in: 0...100, step: 5 ) { Text("Variable") } Text("\(sliderState.variable)") ScrollView{ LazyVGrid(columns: flexibleColumn, spacing: 20) { ForEach(thingState.things[0].prefix(64)) { thing in Text(String(thing.variable)) .frame(width: 100, height: 100, alignment: .center) .background(.blue) .cornerRadius(10) .foregroundColor(.white) .font(.title) } } } .padding() } .padding(20) } }
2. 改用结构体存储数组元素(可选优化)
将Thing从类改为结构体,值类型在SwiftUI视图更新时的内存管理更高效,避免不必要的引用计数开销:
struct Thing: Identifiable { let id = UUID() var variable: UInt8 = 0 }
3. 手动控制视图依赖范围(进阶)
如果不想拆分Observable对象,可以使用withObservationTracking限定视图只追踪特定属性的变化,避免数组部分被不必要地重绘:
// 在ContentView的ScrollView部分修改为: ScrollView{ withObservationTracking { LazyVGrid(columns: flexibleColumn, spacing: 20) { ForEach(1...64, id: \.self) { index in Text(String(observing.things[0][index].variable)) .frame(width: 100, height: 100, alignment: .center) .background(.blue) .cornerRadius(10) .foregroundColor(.white) .font(.title) } } } onChange: { // 仅在数组内容变化时触发更新 } } .padding()
内容的提问来源于stack exchange,提问作者Myreauks
相关产品推荐
相关产品推荐

