【问题标题】:Swift: Creating an Array with a Default Value of distinct object instancesSwift:创建具有不同对象实例默认值的数组
【发布时间】:2015-12-31 12:07:55
【问题描述】:

我注意到 使用默认值创建数组 中的行为有点奇怪( 并且很危险,恕我直言)。如Swift 2.1: Collection Types中所述

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

重点是:默认值相同;为了理解它是如何工作的,我尝试创建这个示例类的元素数组

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

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

这是获取 不同对象实例 数组的方法,尽可能简洁和智能,使用相同的默认值(不是相同的实例,而是使用相同的默认值)?

【问题讨论】:

    标签: arrays swift initialization instance instantiation


    【解决方案1】:

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

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

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

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

    一个可能的解决方案:

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

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

    如果你经常需要,那么你可以定义一个数组 init 采用“自动关闭”参数的方法:

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

    【讨论】:

      【解决方案2】:

      斯威夫特 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)
      

      【讨论】:

        猜你喜欢
        • 2022-01-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多