一尘不染

Swift:使用不同对象实例的默认值创建一个数组

swift

创建具有默认值的数组时,* 我注意到了一些怪异( 和危险的恕我直言 )行为。如Swift
2.1中所述:集合类型

*

Swift的Array类型还提供了一个初始化程序,用于创建一个特定大小的数组,并将其所有值设置为相同的默认值。您向此初始值设定项传递要添加到新数组中的项目数(称为count)和适当类型的默认值(称为repeatedValue):

关键是: 相同的默认值 ;为了了解它是如何工作的,我尝试创建此示例类的元素数组

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
  }
}

和此测试代码:

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)")
}

给出:

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

使用要添加到新数组中的项数以及适当类型的默认值来明确证明初始化程序是: 相同的对象实例

哪种方法尽可能简洁明了,才能获得一组具有相同默认值(不是同一实例,而是许多使用相同默认值初始化的实例)实例化的 不同对象实例


阅读 272

收藏
2020-07-07

共1个答案

一尘不染

类是引用类型,因此-正如您所注意到的-中的所有数组元素

var users = [User](count: howManyUsers, repeatedValue:User(thinkTime: 10.0))

引用相同的对象实例(首先创建该实例,然后将其作为参数传递给数组初始化器)。

对于struct类型,您将获得不同的结果。

可能的解决方案:

var users = (0 ..< howManyUsers).map { _ in User(thinkTime: 10.0) }

在这里,User为每个数组索引创建一个实例。

如果经常需要,则可以定义一个带有“ autoclosure”参数的数组初始化方法:

extension Array {
    public init(count: Int, @autoclosure elementCreator: () -> Element) {
        self = (0 ..< count).map { _ in elementCreator() }
    }
}

var users = Array(count: howManyUsers, elementCreator: User(thinkTime: 10.0) )

现在,第二个参数User(thinkTime: 10.0)由编译器包装到一个闭包中,并对每个数组索引执行闭包。


Swift 3更新:

extension Array {
    public init(count: Int, elementCreator: @autoclosure () -> Element) {
        self = (0 ..< count).map { _ in elementCreator() }
    }
}
2020-07-07