Lodewijck
Lodewijck

Reputation: 416

For in gives let instead of var

I'm struggling with a for-in-loop in Swift. I have two for loops and I expected them be equivalent but the first gives an error and the second works as I expected. Can someone explain me why it's working differently?

protocol Slide {
    var title: String { get set }
}

class BasicSlide: NSObject, Slide {
    var title: String = "Title"
}

var slides: [Slide]?
slides = [BasicSlide()]

for slide in slides! {
    slide.title = "New title" // Cannot assign to property: 'slide' is a 'let' constant
}

for var i in 0 ..< slides!.count {
    slides![i].title = "New title"
}

Upvotes: 2

Views: 4183

Answers (1)

matt
matt

Reputation: 535765

As you rightly say, slide is a constant in this expression:

for slide in slides! {
    slide.title = "New title" // Cannot assign to property: 'slide' is a 'let' constant
}

If you need to mutate your slide, simply take a var reference to it:

for slide in slides! {
    var slide = slide
    slide.title = "New title" // fine
}

(Do not use the for var syntax, as it will soon be abolished from the language.)

However, in your example there's a much better way: declare your protocol like this:

protocol Slide : class {
    var title: String { get set }
}

Now this code is legal!

for slide in slides! {
    slide.title = "New title"
}

Why? Because you've now guaranteed that the adopter of Slide is a class, and a class is a reference type and can be mutated in place. The only reason this failed before is that Swift was afraid the adopter might be a struct.

Upvotes: 6

Related Questions