变量'xxx'从未发生变异,请考虑更改为'let'

时间:2015-06-10 03:21:32

标签: swift optional

更新为xcode7-beta 我遇到了一种新的警告。这是我的代码

override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
    var attributes: [UICollectionViewLayoutAttributes]? = super.layoutAttributesForElementsInRect(rect)
    if let layoutInfo = self.layoutInfo {
        attributes?.append(layoutInfo)
    }
    return attributes
}

警告信息是 Variable 'attributes' was never mutated, consider changing to 'let' constant

为什么xcode会说Variable 'attributes' was never mutated

问题更新

当我将代码更改为

时,警告消失了
override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
    var attributes: [UICollectionViewLayoutAttributes]? = super.layoutAttributesForElementsInRect(rect)
    if let layoutInfo = self.layoutInfo {
        attributes!.append(layoutInfo)
    }
    return attributes
}

所以强行展开可以把它带走。但它可能不是一件好事吗?

5 个答案:

答案 0 :(得分:21)

他们在WWDC视频和发行说明中谈到了这一点。

如果您尽可能使用let而不是var,那么您的表现一直都会得到更好,更好的速度(更快的速度,更小的空间)。这告诉编译器这个东西是常量,而不是变量,这个事实允许编译器优化所有类型的东西。

但编译器不能这样做,除非你 尽可能地使用let。它不会将var更改为<{1}}

因此,在Swift 2中,编译器会在构建时进行更智能的分析,并在您使用let时使用var警告您。最终这个功能将正常工作,此时您应该接受编译器的建议!

答案 1 :(得分:10)

这也让我发疯了。每当我有一个类并且我更改成员属性时,它仍然告诉我应该使变量成为常量。例如:

class X { 
    var name = ""
}

var xInstance = X()
xInstance.name = "my name"

我认为,编译器是正确的。 xInstance是一个常量。它在初始化期间被分配了指向X实例的指针,并且永远不会被赋予另一个值。所以xInstance是不变的。它指向的类不是常数。 这在C或C ++这样的语言中更为明显,但当您意识到所有类实例都是指向堆支持类的指针时,这是有道理的。

对于那些了解C ++的人

xInstance相当于:

X *xInstance

将其改为let意味着它变为:

X * const xInstance

我认为大多数人会直觉地认为快速声明等同于

X const * xInstance

答案 2 :(得分:2)

通过使用let声明一个常量,可以确保永远不会更改它。这有助于确保您以后不会意外地更改它,并且(理论上)它可以帮助优化器生成更快的代码。

如果您使用var声明变量,并且您不打算更改变量或调用变异方法,则使用let可帮助您强制执行该合同。

答案 3 :(得分:1)

您已将该对象创建为var对象,但该对象的值不会更改,然后才能让它更好。就是这样。

根据Apple Developer Guidelines,如果该对象的值将要更改,则创建var对象,否则创建let变量。最佳实践

答案 4 :(得分:1)

您的代码暗示如果attributes为非零,则self.layoutInfo可能会发生变异

也许警告说没有路径导致self.layoutInfo非零,因此属性不需要变量。

检查可能导致self.layoutInfo数据的条件