Swift中的nil对象数组

时间:2014-06-12 17:33:38

标签: swift

我的类有一个属性,在其他语言中,它将是一个简单的字符串数组,它将在对象的实例化中初始化。在Swift中,我提出了以下内容:

class Foo {
  var myArray: (String!)[]!

  init(arraySize: Int, sourceOfData: SomeOtherClass){

    myArray = Array<(String!)>(count: arraySize, repeatedValue:nil)

    /* ... code to set the elements of the array using sourceOfData ... */
  }
}

这是我能够编译允许预分配数组元素的代码的唯一方法。但是,我认为所有这些感叹号都会让我的代码难以阅读。

我知道我可以将repeatedValue更改为任意非零字符串,并将类型简化为String[]!,但这将是一个黑客攻击。

另外,我可以这样做:

class Foo {
  let myArray: String[] = []

  init(sourceOfData: SomeOtherClass){

    /*loop over sourceOfData*/{
      myArray.append(/* computed String value */)
    }
  }
}

然而,这显然性能更差,因为编译器无法猜测我的Array的长度并为其分配连续的内存块。通常情况下,我不太关心优化代码的这一部分的性能,但是对于这个类而言,它是至关重要的。

有没有办法在不影响性能的情况下使用易读类型?

2 个答案:

答案 0 :(得分:4)

只要您在myArray填充init(),就不需要将sourceOfData标记为可选。如果你可以使用地图循环class Foo { var myArray: String[] init(sourceOfData: SomeOtherClass) { myArray = sourceOfData.map { return $0.computeStringValue() } } } ,那么这样就可以了:

class Foo {
  var myArray: String[]

  init(sourceOfData: SomeOtherClass) {
    myArray = Array<String>(count: SomeOtherClass.count, repeatedValue: "")

    for i, item in enumerate(sourceOfData) {
      myArray[i] = item.computeStringValue()
    }
  }
}

如果你真的需要使用一个循环,并且你至少可以确定你需要多大的数组,你可以这样做:

{{1}}

关于性能的最后一点注意事项:LLVM是一个非常复杂的编译器。你说它显然是更糟糕的性能&#34;,但这是静态分析实际上可以确定数组的适当大小的那种代码。我建议使用您的用例的实际数据对其进行分析。

答案 1 :(得分:2)

您可以在Array上使用reserveCapacity方法。这将确保有足够的预分配内存来保存您的数据。

class Foo {
  var myArray: String[]

  init(sourceOfData: SomeOtherClass) {
    myArray.reserveCapacity(sourceOfData.count)
    // loop over data calling .append()
  }
}