21

I have an array of structs:

struct CalendarDate {
    var date: NSDate?
    var selected = false
}

private var collectionData = [CalendarDate]()

Which I simply populate with a date like this:

    for _ in 1...7 {
        collectionData.append(CalendarDate(date: NSDate(), selected: false))
    }

So when you tap on a collectionView, I simply want to loop through the data and mark them all as False.

    for c in collectionData {
        c.selected = false  ///ERROR: Cannot assign to 'selected' in 'c'
    }

Why do I get this error?

If I do this, it works fine but I want to know what I did wrong above:

    for i in 0..<collectionData.count {
        collectionData[i].selected = false
    }
2
  • I'm not sure about this answer, so I'll post it as a comment, but have you tried doing for var c in collectionData? I know it works in other languages. Commented Mar 30, 2015 at 22:15
  • Yeah, I tried that, not valid syntax. Too bad, because that would have solved my problem ;( Commented Mar 30, 2015 at 22:16

3 Answers 3

32

As I understand it, the iterator

for c in collectionData

returns copies of the items in collectionData - (structs are value types, not reference types, see http://www.objc.io/issue-16/swift-classes-vs-structs.html), whereas the iteration

for i in 0..<collectionData.count

accesses the actual values. If I am right in that, it is pointless to assign to the c returned from the iterator... it does not "point" at the original value, whereas the

collectionData[i].selected = false

in the iteration is the original value.

Some of the other commentators suggested

for (var c) in collectionData

but although this allows you to assign to c, it is still a copy, not a pointer to the original, and though you can modify c, collectionData remains untouched.

The answer is either A) use the iteration as you originally noted or B) change the data type to a class, rather than a struct.

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

1 Comment

Here is another possibility for structs: for i in collectionData.indices { ... }
5

because each 'c' is by default let, and this is a new instance of CalendarDate and the value of array at index copied to this for each step of for, and 'c' isn't pointer to the index of the array and it is just a copy of index, so if you set a new value to this, the new value does not apply in array. but 'i' is used as index of array and can directly manipulate the values of array.

Comments

4

If you are using structs they are copies in the array. So even changing them only changes the copy, not an actual object in the array.

You have to make them a variable in the loop to be editable copy, and reassign them into the array right back.

If they are classes and not structs, than you don't have to reassign part, just do the var thing.

for (index, var c) in collectionData.enumerated() {
        c.selected = false
        collectionData[index] = c
    }

1 Comment

I had to use Structs in my project and this saved my life. Thanks

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.