这种Swift语法有效吗?

时间:2015-06-23 09:28:16

标签: ios swift syntax

每次访问getter时,这个for循环是否会触发?或者Swift在幕后缓存它' ?

var colors: [UIColor] {
get {
  var colors = [UIColor]()
  let palette = [UIColor.redColor(), UIColor.greenColor(), UIColor.blueColor(), UIColor.orangeColor(), UIColor.purpleColor(), UIColor.yellowColor()]
  var paletteIndex = 0
  for _ in 0..<photos.count {
    colors.append(palette[paletteIndex])
    paletteIndex = paletteIndex == (palette.count - 1) ? 0 : ++paletteIndex
  }
  return colors
}
}

在objective-c中,像这样的吸气剂将位于私人ivar的支票后面,这样ivar就会被设置一次,然后ivar会在后续的呼叫中返回。

5 个答案:

答案 0 :(得分:2)

每次调用getter时都会触发。绝不可能将其优化掉。

您可能希望将预设颜色数组与照片属性保持同步,即在设置照片时直接更改。

我也不喜欢那个地方紧密耦合似乎没必要。我认为重构这个并且只返回给定照片索引的特定颜色(使用模运算符是微不足道的)可能是值得的。

所以我的建议是将调色板保存为实例变量,然后制作方法return palette[index % palette.count],它会立即给出正确的颜色。

答案 1 :(得分:1)

我将这样做,正如@Eiko所建议的

let palette = [UIColor.redColor(), UIColor.greenColor(), UIColor.blueColor(), UIColor.orangeColor(), UIColor.purpleColor(), UIColor.yellowColor()]

override func viewDidLoad() {
    super.viewDidLoad()
    ...
}

override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCellWithReuseIdentifier("AnnotatedPhotoCell", forIndexPath: indexPath) as UICollectionViewCell
    cell.contentView.backgroundColor = palette[indexPath.item % palette.count]
    return cell
}

答案 2 :(得分:0)

您使用的computed property实际上并未存储值,并且计算的命名值或计算属性的值不会存储在内存中。它在快速的编程书中

答案 3 :(得分:0)

您可以使用延迟初始化:

lazy var colors : [UIColor] = {
    var colors = [UIColor.redColor]
    // blablabla
    return colors
}()

当您第一次尝试访问颜色时,它将只运行一次。但是,如果颜色需要在整个课程期间更新,我建议使用函数重新计算它们:

func recalcColors() -> [UIColor] {
    var colors = [UIColor.redColor]
    // blablabla
    return colors
}

lazy var colors = recalcColors()

当您需要更新它们时,您可以拨打colors = recalcColors()

答案 4 :(得分:0)

从Swift逻辑的角度来看,它每次都会运行,但是,在某些情况下,优化器可以将整个计算转换为常量,在这种情况下无关紧要。

有两件事阻碍了它:palette数组和photos.count属性。从理论上讲,palette数组永远不会改变,但编译器无法知道这一点,因为它不知道像redColor()这样的函数总是返回相同的值。因此,将数组创建提升到属性之外。

photos.count可能没有修复,假设photos在程序过程中动态变化大小。

但这会给你带来同样的效果,根本不需要创建任何数组:

struct PaletteCycler {
    let palette = [
        UIColor.redColor(), UIColor.greenColor(),
        UIColor.blueColor(), UIColor.orangeColor(),
        UIColor.purpleColor(), UIColor.yellowColor(),
    ]

    subscript(idx: Int)->UIColor {
        return palette[idx%palette.count]
    }
}

let colors = PaletteCycler()

由于一切都是常量,因此获取颜色的运行时成本非常低。与原始版本不同,这不会每次都创建一个数组。由于mod和fetch非常有效,并且palette变量是常量,因此它应该很快。

顺便说一下,如果事情不那么稳定并且你真的想要一个数组,你可以使用map重写你的循环:

let palette = [
    UIColor.redColor(), UIColor.greenColor(),
    UIColor.blueColor(), UIColor.orangeColor(),
    UIColor.purpleColor(), UIColor.yellowColor(),
]

var colors: [UIColor] = {

    // Swift 2.0 syntax. For 1.2, write
    // indices(photos).map
    return photos.indices.map {
        palette[$0 % palette.count]
    }

}