I noticed a bit weird (and dangerous IMHO) behavoir in Creating an Array with a Default Value. As stated in Swift 2.1: Collection Types
Swift’s Array type also provides an initializer for creating an array of a certain size with all of its values set to the same default value. You pass this initializer the number of items to be added to the new array (called count) and a default value of the appropriate type (called repeatedValue):
The point is: same default value; in order to understand how it work, I tried to create an array of elements of this example class
class User {
private struct Shared {
static var sequence: Int = 0
}
var id: Int
var thinkTime: NSTimeInterval // typealias di Double
init (thinkTime: NSTimeInterval) {
User.Shared.sequence = User.Shared.sequence+1
id = User.Shared.sequence
self.thinkTime = thinkTime
}
}
and this testing code:
let howManyUsers: Int = 3
var users = [User](count: howManyUsers, repeatedValue:User(thinkTime: 10.0))
let u2: User = User(thinkTime: 10)
let u3: User = User(thinkTime: 10)
users.append(u2)
users.append(u3)
users[1].thinkTime = 20
users[3].thinkTime = 30
for u in users {
print("User id:\(u.id) thinktime:\(u.thinkTime)")
}
gives:
User id:1 thinktime:20.0
User id:1 thinktime:20.0
User id:1 thinktime:20.0
User id:2 thinktime:30.0
User id:3 thinktime:10.0
that definitively proof the initializer with the number of items to be added to the new array and a default value of the appropriate type are: the same object instance
Which is the way, as concise and smart as possible, to obtain a array of distinct object instances , instatiated with the same default value ( not the same instance but a number of instances initialized with the same default value ) ?
Classes are reference types, therefore – as you noticed – all array elements in
reference the same object instance (which is created first and then passed as an argument to the array initializer).
For a
struct
type you would get a different result.A possible solution:
Here, a
User
instance is created for each of the array indices.If you need that frequently then you could define an array init method which takes an "autoclosure" parameter:
Now the second argument
User(thinkTime: 10.0)
is wrapped by the compiler into a closure, and the closure is executed for each array index.Update for Swift 3: