0

I have a simple array of structs

var fields: [ProfileField]?

when I try to iterate through this array, swift shows me error on this code:

guard let _fields = fields else {return}
for field in _fields {
}

the error is:

Cannot use mutating getter on immutable value: 'field' is a 'let' constant

And this code compiles well:

for var field in _fields {
}

Why do I need to declare field as var?

6
  • @MikePollard guard let _fields = fields else {return} Commented Oct 30, 2015 at 14:25
  • 6
    I think you need to reveal what you're up to in your for loop Commented Oct 30, 2015 at 14:29
  • 2
    I guess you're doing something that mutates field Commented Oct 30, 2015 at 14:29
  • 2
    Yes, when your struct was a class it was a reference. Now it's a struct and a value, which if you declare with let you can't change. Commented Oct 30, 2015 at 14:31
  • 2
    Possible duplicate of stackoverflow.com/questions/29777891/…. Commented Oct 30, 2015 at 14:38

1 Answer 1

2

A “mutating getter” in Swift is a property whose get block has the mutating modifier. For example, if your ProfileField looked like this:

struct ProfileField {
    var accessCount: Int = 0

    var x: Int {
        mutating get {    // ← mutating getter here
            accessCount++
            return x
        }
    }
}

…then this code would generate your “Cannot use mutating getter on immutable value” error:

for field in _fields {
    print(field.x)
}

Even though it doesn’t look like field.x modifies field, it does: it increments accessCount. That’s why you must say var field to make field mutable. (For loop iterators are let by default.)

Without seeing either your ProfileField or the body of your for loop, it’s impossible to say exactly why this occurs in your case. If you are not using mutating get in ProfileField itself, it may be happening in a struct nested within ProfileField.

Sign up to request clarification or add additional context in comments.

2 Comments

Great! Thank you so much for the "Even though" - now I understand that accessCount is changing! Best of the best!
Glad it helped. Further surprising detail (that makes sense when you think about it): it’s not accessCount++ that causes the compile error, but the word mutating itself. If a function modifies the struct, you have to declare it mutating, but the converse is not true. You can declare something mutating just to reserve the right to modify the struct even though you don’t. It’s an API choice.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.