您如何解决“不能在不可变值上使用变异成员:'自我'是不可变的”?

时间:2020-09-15 04:13:26

标签: swift swiftui

如何解决错误不能在不可变值上使用变异成员:'{self}是不可变的在行self.prepareConfetti(screenWidth: CGFloat(geo.size.width))上吗?

关于这个主题有很多StackOverflow问题,但是没有一个对我有帮助。

我的代码:

struct ContentView: View {
    @State private var confettiTimer = Timer.publish(every: 0.0166, on: .main, in: .common).autoconnect()
    private var confettiX = [CGFloat]()
    private var confettiY = [CGFloat]()
    private var confettiWidth = [CGFloat]()
    private var confettiHeight = [CGFloat]()
    private let numOfConfetti: Int = 80
 
    var body: some View {
        GeometryReader { geo in
            ForEach(0..<self.confettiY.count, id: \.self) { i in
                Path { path in
                    path.addRect(
                        CGRect(
                            x: self.confettiX[i],
                            y: self.confettiY[i],
                            width: self.confettiWidth[i],
                            height: self.confettiHeight[i]
                        )
                    )
                }
                .fill(Color.black)
                .onAppear {
                    self.prepareConfetti(screenWidth: CGFloat(geo.size.width)) //This gives the error
                }
                .onReceive(self.confettiTimer) { time in
                    
                }
            }
        }
    }
    
    mutating func prepareConfetti(screenWidth: CGFloat) {
        for _ in 0..<self.numOfConfetti {
            let x: CGFloat = 0.0
            let y = screenWidth * 0.5
                
            self.confettiX.append(x)
            self.confettiY.append(y)
            self.confettiWidth.append(20.0)
            self.confettiHeight.append(20.0)
        }
    }
    
}

1 个答案:

答案 0 :(得分:0)

您不能以这种方式更改SwiftUI视图,应该将这些属性用作状态

struct ContentView: View {
    @State private var confettiTimer = Timer.publish(every: 0.0166, on: .main, in: .common).autoconnect()
    
    @State private var confettiX = [CGFloat]()
    @State private var confettiY = [CGFloat]()
    @State private var confettiWidth = [CGFloat]()
    @State private var confettiHeight = [CGFloat]()
    private let numOfConfetti: Int = 80
 
    var body: some View {
        GeometryReader { geo in
            ForEach(0..<self.confettiY.count, id: \.self) { i in
                Path { path in
                    path.addRect(
                        CGRect(
                            x: self.confettiX[i],
                            y: self.confettiY[i],
                            width: self.confettiWidth[i],
                            height: self.confettiHeight[i]
                        )
                    )
                }
                .fill(Color.black)
                .onAppear {
                    self.prepareConfetti(screenWidth: CGFloat(geo.size.width)) //This gives the error
                }
                .onReceive(self.confettiTimer) { time in
                    
                }
            }
        }
    }
    
    private func prepareConfetti(screenWidth: CGFloat) {
        for _ in 0..<self.numOfConfetti {
            let x: CGFloat = 0.0
            let y = screenWidth * 0.5
                
            self.confettiX.append(x)
            self.confettiY.append(y)
            self.confettiWidth.append(20.0)
            self.confettiHeight.append(20.0)
        }
    }
}