Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift Array(repeating:, count:) behaviour

Tags:

arrays

swift

Why does only one element from the labels array appear as a subview of view, specifically when using Array(repeating:, count:)?

let labels = Array(repeating: UILabel(), count: 7)

print(labels.count) //7

let view = UIView()

for label in labels {
    view.addSubview(label)
}

print(view.subviews.count) //1

test in the Playground

like image 729
Cameron Avatar asked Dec 10 '22 08:12

Cameron


2 Answers

This is the expected behaviour for Array.init(repeating:count:). Think of its implementation as:

// not real code! This is just to illustrate what happens!
init(repeating repeatedValue: Array.Element, count: Int) {
    for _ in 0..<count {
        self.append(repeatedValue)
    }
}

Here, no new labels are created. There are just 7 references pointing to the same label.

It's not useful to create 7 labels this way anyway. They would all be in the same position and have the same size and text. It would look as if there is only one label. So, just use a for loop.

EDIT

Here is an extension that has the behaviour you want:

extension Array {
    init(repeating: (() -> Element), count: Int) {
        self = []
        for _ in 0..<count {
            self.append(repeating())
        }
    }
}

Use it like

Array(repeating: UILabel.init, count: 7)

Since this isn't very useful in creating labels, we can change the closure type to include a Int parameter. This way we can create different labels:

init(repeating: ((Int) -> Element), count: Int) {
    self = []
    for i in 0..<count {
        self.append(repeating(i))
    }
}

// a horizontal row of square labels!
Array(repeating: { UILabel(frame: CGRect(x: $0 * 100, y: 0, width: 50, height: 50)) })

This kinda feels like a for loop now...

like image 92
Sweeper Avatar answered Jan 11 '23 16:01

Sweeper


This happens because Array(repeating:count:) creates an array of 7 variables that are pointing to the same label.

Since all 7 elements are pointing to the same instance, the count of the subviews will be 1.

like image 35
Tamás Sengel Avatar answered Jan 11 '23 15:01

Tamás Sengel