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

Variable 'xxx' was never mutated, consider changing to 'let'

已更新为 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
}

所以强制展开可以把它拿走。但这可能不是一件好事吧?

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

如果您使用 var 声明了一个变量,并且您不打算更改它或对其调用变异方法,那么使用 let 可以帮助您执行该契约。

您已将该对象创建为 var 对象,但该对象的值没有改变,然后最好让它 let。而已。

根据 Apple 开发人员指南,如果对象的值要更改,则创建 var 对象,否则创建 let 变量。最佳实践

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

如果您尽可能使用 let 而不是 var,您总是可以获得更好的性能(更快的速度,更小的 space)。这告诉编译器这个东西是一个常量,而不是一个变量,这个事实允许编译器优化各种东西。

但是编译器无法做到这一点,除非你尽可能使用let。它不会将 var 更改为 let 你。

因此,在 Swift 2 中,编译器会在构建时进行更智能的分析,如果您在本可以使用 let 的地方使用 var,则会发出警告。最终此功能将正常工作,此时您应该听取编译器的建议!

您的代码暗示如果 self.layoutInfo 不为零

,则 attributes 可能会发生变化

也许警告说没有路径导致 self.layoutInfo 为非 nil,因此属性不需要是 var。

检查什么条件(如果有的话)会导致 self.layoutInfo 有数据

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

class X { 
    var name = ""
}

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

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

对于了解 C++ 的人

xInstance 等同于:

X *xInstance

改为 let 意味着它变为:

X * const xInstance

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

X const * xInstance

为什么会出现这个警告?

因为在 Swift 中,“let”表示“值是常量”并允许编译器进行一些优化,因此“let”比“var”快",
由于“Swift 2”,如果我们在任何地方检测到我们可以使用“let”而使用“var”,编译器都会发出警告。

Class 与结构

但是,在 Swift 中,“class”是一个引用类型(就像在 Java 中一样),这意味着“值”只是“一个引用 and/or指向实际数据的指针。

即使我们将“let”与“class”一起使用,指向的“数据”也永远不会恒定(并且始终可变)。
因此,如果更改“数据”是一件大事并且不应被忽视,请考虑使用 struct.

在 Swift 中,“struct”是一个值类型,除非它是用“var”(或“inout”在“func" parameters),它所持有的“数据”的任何变化都会导致编译错误。

Basically same as const keyword available in C and C++ languages, but in C++ we don't need to migrate from "class" to a complete different type, jsut to have mutability sensitive class.

That's a plus for C++, but it fades to nothing, once we see the other C++ overcomplications.