我最近正在研究一些测试代码,构建愚蠢的视图层次结构,然后我遇到了一些代码,这些代码让我有点眯眼。
var parentView: UIView = UIView() //Warning here
parentView.addSubview(UIImageView())
第一行是以下警告:
变量'parentView'从未发生变异;考虑改为'让'常数
我很困惑为什么这个元素没有,或者为什么编译器认为它不是,正在变异。我想也许Swift正在检测对象中的集合是否正在变异,而不是对象本身的属性。这导致我尝试以下方法:
let strings: [String] = []
strings.append("Hi") //This is an error
鉴于上面的代码,我能想到的唯一解释是某处有一个bug。我错过了某个允许这种情况有意义的关键字吗? C ++的“可变”关键字沿线的东西?
如果它不是一个bug,我希望看到这个场景在一个不从UIObject继承的类中重新创建,所以我可以理解是什么导致了这个。
答案 0 :(得分:3)
这不是错误。对于类实例(它们是引用类型),例如在UIView
实例中,即使实例本身是常量(let)
,也可以改变实例属性。另一方面,数组在Swift中被视为值类型,并且是常量数组的成员( let arr ...
)可能不会发生变异。
因此,你从来没有实际变异parentView
本身(parentView = UIView()
将是它自身的变异),只有它的成员,在这种情况下,它是有意义的(如编译器注释)标记parentView
为常数。
如果您创建结构的实例并将该实例分配给a 常量,您无法修改实例的属性,即使它们也是如此 被声明为变量属性:
...
此行为是由于结构是值类型。当一个实例 值类型的值被标记为常量,因此它的所有属性都是。
对于类,引用类型,不同。如果你 将一个引用类型的实例分配给一个常量,你仍然可以 更改该实例的变量属性。
来自Language Guide - Properties。
...
你实际上已经在整个过程中广泛使用了价值类型 前几章。实际上,Swift-integers中的所有基本类型, 浮点数,布尔值,字符串,数组和词典 - 是 值类型,并作为幕后结构实现。
所有结构和枚举都是Swift中的值类型。这意味着 您创建的任何结构和枚举实例 - 以及任何值 它们作为属性的类型 - 在传递时始终被复制 在你的代码中。