Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

'Cannot use mutating getter on immutable value: 'self' is immutable' when iterating?

Does anyone know why the self.indexCount in the ForEach is giving the error Cannot use mutating getter on immutable value: 'self' is immutable error? I can provide aView with indexCount, but it's not very convenient. I'm not changing indexCount. Is this a SwiftUI bug or intentional?

struct aView: View {
    let array: [[String]]
    lazy var indexCount: Int = array[0].count

    var body: some View {
        VStack {
            ForEach(0..<self.indexCount, id: \.self) { index in
                Text("Hello World")
           }
        }
    }
}
like image 908
HelloWorld Avatar asked Dec 31 '22 05:12

HelloWorld


2 Answers

It's intentional. In SwiftUI, only @State variables can change. You can't use a lazy var like that. Replace it with a computed property:

var indexCount : Int { array[0].count }

That's better anyway, because it will always be correct: indexCount will always be the current size of array[0]), whereas your way, the value will freeze at whatever the count is the first time it is fetched.

like image 73
matt Avatar answered Jan 05 '23 17:01

matt


lazy always results in a mutation when the value is initialized. Therefore, you cannot use it in a non-mutating context.

body is not mutating so you won't be able to use lazy there. You get the same error with this minimal example:

struct LazyUser {
    lazy var something: Bool = { false } ()
}

func useSomething() {
    let notOk = LazyUser()
    var ok = LazyUser()
    _ = notOk.something // ERROR: Cannot use mutating getter on immutable value: 'notOk' is a 'let' constant
    _ = ok.something
}

There is a thread about this on the Swift Forums.

like image 43
arsenius Avatar answered Jan 05 '23 17:01

arsenius