1

I am working a project and have come across this error when iterating through a for in loop like this:

class CustomClass {
    
    var nameNum : Int { didSet { self.name = "CustomClass \(nameNum)" } }
    var name : String
    
    init() {
        nameNum = 0
        self.name = "CustomClass \(nameNum)"
    }
}

var myArray : [CustomClass] = [CustomClass](repeating: CustomClass(), count: 5)

for _class in myArray.indices {
    myArray[_class].nameNum = _class
}

print("\n")
for _class in myArray.indices {
    print("Item \(_class): \(myArray[_class].name)")
}

I get the following output:

Item 0: CustomClass 4

Item 1: CustomClass 4

Item 2: CustomClass 4

Item 3: CustomClass 4

Item 4: CustomClass 4

This does not make sense to me as I thought I would get the following output instead:

Item 0: CustomClass 0

Item 1: CustomClass 1

Item 2: CustomClass 2

Item 3: CustomClass 3

Item 4: CustomClass 4

Any help as to why this doesn't work or to how to go about fixing it is appreciated, thanks!

3
  • _class is a misleading name in the second loop. It's actually an index Commented Jul 28, 2017 at 0:29
  • 1
    Related: stackoverflow.com/questions/32921425/… Commented Jul 28, 2017 at 5:29
  • Thanks @MartinR that helps explain it to me. Commented Jul 28, 2017 at 14:30

2 Answers 2

1

You should change your array initialization to

var myArray : [CustomClass] = (0..<5).map { _ in CustomClass() }

from

var myArray : [CustomClass] = [CustomClass](repeating: CustomClass(), count: 5)

Complete Code:

class CustomClass {
    
    var nameNum : Int { didSet { self.name = "CustomClass \(nameNum)" } }
    var name : String
    
    init() {
        nameNum = 0
        self.name = "CustomClass \(nameNum)"
    }
}

var myArray : [CustomClass] = (0..<5).map { _ in CustomClass() }

for _class in myArray.indices {
    myArray[_class].nameNum = _class
}

print("\n")
for _class in myArray.indices {
    print("Item \(_class): \(myArray[_class].name)")
}

The reason is that your code, actually creates an instance of CustomClass and adds it at all 5 indexes of array where as you are expecting 5 different instance of CustomClass. If the same instance is added 5 times, then all of them will have the last set value which in your case is 4.

Item 0: CustomClass 0

Item 1: CustomClass 1

Item 2: CustomClass 2

Item 3: CustomClass 3

Item 4: CustomClass 4

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

1 Comment

Good to hear that.
1

Why are you setting nameNum to 0 in the initializer, if you're immediately going to change it? Just combine the operations:

class CustomClass {
    var nameNum: Int
    var name: String { return "CustomClass \(nameNum)" }

    init(nameNum: Int) {
        self.nameNum = nameNum
    }
}

var myArray = (0..<5).map(CustomClass.init(nameNum:))

for (index, element) in myArray.enumerated() {
    print("Item #\(index): \(element.name)")
}

Also, if name always has a value derived from nameNum, then it's better to have it be a computed property whose derived from nameNum, rather than having the responsibility of setting it fall to a side effect of setting nameNum.

1 Comment

Thank you +1 for the combined operations

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.