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

Swift: Creating an Array with a Default Value of distinct object instances

我注意到在 Creating an Array with a Default Value 中有一点奇怪(和危险的恕我直言)行为。如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):

重点是:相同的默认值;为了理解它是如何工作的,我尝试创建这个例子的元素数组 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
  }
}

和这个测试代码:

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

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

这是一种尽可能简洁和智能的方法,可以获取 不同的对象实例数组 ,实例化具有相同的默认值(不是同一个实例,而是一个数字使用相同默认值初始化的实例数 ) ?

类 是引用类型,因此——如您所见——所有数组

中的元素
var users = [User](count: howManyUsers, repeatedValue:User(thinkTime: 10.0))

引用相同的对象实例(先创建然后再创建 作为参数传递给数组初始值设定项)。

对于 struct 类型,您会得到不同的结果。

可能的解决方案:

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

此处,为每个数组索引创建一个 User 实例。

如果你经常需要,那么你可以定义一个数组 init 采用 "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) 被 编译器变成一个闭包,闭包为每个执行 数组索引。


Swift3 的更新:

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

Swift 5

extension MSRoom {
    static var dummyDefaultRoom: MSRoom = {
        let members = MSRoom.Member.dummyMembers(maxCount: 6)
        let ownerUser = members.first!.user
        var room = MSRoom(id: "98236482724", info: .init(name: "Ahmed's Room", description: "your default room", isPrivate: true), owner: ownerUser)
        room.dateCreated = Date(timeIntervalSince1970: 1565222400)
        room.currentMembers = members
        return room
    }()

}

let rooms = [MSRoom](repeating: MSRoom.dummyDefaultRoom, count: 10)