如何防止SwiftUI在ForEach循环中重新初始化初始化视图?

如何防止SwiftUI在ForEach循环中重新初始化初始化视图?,swiftui,Swiftui,我有一个按钮,可以将CircleInfo类型的新对象添加到名为circleArray的数组中!这个数组将用于为ForEach循环提供数据,除了我注意到的一个大问题之外,所有的都在工作 问题:当我向数组添加新对象时,更新数组的动作也会让ForEach更新自身,它会让应用程序和内存的视图比简单的圆圈更详细,因为它会再次开始初始化初始化视图!例如,我们在屏幕上得到了10个圆,一旦我添加了新的圆,Foreach将渲染所有渲染的10个圆加上新的一个! 也许你会说,这是一种快速用户界面的工作方式,它通过微小

我有一个按钮,可以将CircleInfo类型的新对象添加到名为circleArray的数组中!这个数组将用于为ForEach循环提供数据,除了我注意到的一个大问题之外,所有的都在工作

问题:当我向数组添加新对象时,更新数组的动作也会让ForEach更新自身,它会让应用程序和内存的视图比简单的圆圈更详细,因为它会再次开始初始化初始化视图!例如,我们在屏幕上得到了10个圆,一旦我添加了新的圆,Foreach将渲染所有渲染的10个圆加上新的一个! 也许你会说,这是一种快速用户界面的工作方式,它通过微小的变化绘制屏幕,但我告诉你,随着越来越多的数据,它会消耗大量内存和CPU

我的目标:我想找到一种向屏幕添加新对象的新方法,更可能是添加过多的对象,或者是那些不需要的对象!因为一旦我们改变了阵法的道具或者阵法的范围,它就会再次被全数吸引




实现目标的最简单方法是使用
CircleView
数组,而不是
CircleInfo

首先使
CircleView
可识别:

struct CircleView:视图,可识别{
let id:UUID=UUID()
…
然后在
ForEach


结构ContentView:View{
@状态变量circleArray:[CircleView]=[CircleView]()
var body:一些观点{
GeometryReader{中的几何体
颜色
黄先生
.ignoresSafeArea()
ForEach(circleArray){item in
项目
.位置(x:geometry.size.width/2,y:20*CGFloat(项目索引)+100)
}
}
.覆盖(按钮,对齐:对齐.底部)
}
var按钮:一些视图{
按钮(“添加圆”){circleArray.append(CircleView(circleInfo:circleInfo(),索引:circleArray.count))}
}
}

你肯定会少用CPU。

我喜欢你的方式,你以前遇到过这个问题还是你刚刚找到了答案?@swiftPunk以前从来没有遇到过这个问题,但自从它问世以来,我已经写了很多SwiftUI代码,所以这样做似乎比较自然,每次添加
CircleView
时都不会调用初始值设定项d、 我们都在向数组中添加新项,我在向数组中添加CircleInfo,但你在添加CircleView!为什么我们会得到不同的结果?我的意思是,我们都在为ForEach更新数组,为什么会有这么大的差异?
ForEach
将闭包作为尾随参数。当
@State
变量更改时,它会导致
SwiftUI
变为redraw
ContentView
,它依次使
ForEach
循环通过
circleArray
,并对
circleArray
的每个项目执行闭包。在您的版本中,闭包实例化一个新的
CircleView
,在我的版本中,该角色被委托给按钮,而
CircleView
实例被缓存在<代码>circleArray
struct CircleInfo: Identifiable {

    let id: UUID = UUID()
    let circleColor: Color = Color(red: Double.random(in: 0...1), green: Double.random(in: 0...1), blue: Double.random(in: 0...1))

}
    struct CircleView: View {

    let circleInfo: CircleInfo
    let index: Int

    init(circleInfo: CircleInfo, index: Int) {

        self.circleInfo = circleInfo
        self.index = index
        
        print("initializing circle:", index)
    }

    var body: some View {

        Circle()
            .fill(circleInfo.circleColor)
            .frame(width: 200, height: 200, alignment: .center)
        
    }
    
}
    struct ContentView: View {

    @State var circleArray: [CircleInfo] = [CircleInfo]()

    var body: some View {

        GeometryReader { geometry in

            Color
                .yellow
                .ignoresSafeArea()

            ForEach(Array(circleArray.enumerated()), id:\.element.id) { (index, item) in

                CircleView(circleInfo: item, index: index)
                    .position(x: geometry.size.width/2, y: 20*CGFloat(index) + 100)
                
            }
 
        }
        .overlay(button, alignment: Alignment.bottom)
  
    }

    var button: some View {

        Button("add Circle") { circleArray.append(CircleInfo()) }
  
    }
 
}