逻辑是在数组具有指定数量的元素时清除它。我可以将检查放在Array之外,但是我试图在Array的willSet事件中查看该怎么办。结果是Array中的元素保持静止。
这是代码
var MyArr=[String]() {
willSet{
print("now count is:\(MyArr.count)")
if MyArr.count>2 {
print("now remove all!")
MyArr.removeAll()
}
}
}
MyArr.append("hello")
MyArr.append(",world")
MyArr.append("!")
MyArr.append("too much.")
print("The conent is \(MyArr)")
预计MyArr仅包含一个元素,而实际结果为四个。
答案 0 :(得分:2)
该行为与值类型/引用类型无关
请注意警告
尝试将属性“ MyArr”存储在其自己的willSet中,该属性将被新值覆盖
这意味着修改willSet
中的对象无效。
答案 1 :(得分:2)
引用the Language Guide - Properties - Property Observers [强调我的]:
财产观察员
财产观察员观察并响应财产变化 值。
...
您可以选择定义一个或两个这些观察者 属性:
willSet
在存储值之前被称为 。didSet
在存储新值后立即被调用 。
在尝试使用willSet
属性观察器时,您在willSet
块中观察到的属性的任何变异先于存储{{1} },紧跟在newValue
块之后。这意味着您实际上是在尝试将willSet
的“旧副本”突变为新值之前。
可以说这可能是非法的,因为 ... 注意 在这两个检查的第一个中, 这也是我们可以预期的一种特殊情况,例如 现在,如果在存储新值后更改为将属性更改为 ,则该更改将生效,并且如上所述,不会触发对属性观察器的任何其他调用。应用于您的示例:myArr
的任何突变都应导致调用任何属性观察者,从而导致属性观察者内部的属性发生变异(引用的变异对于引用类型为em>或对于值类型为值)可能会导致对属性观察器的递归调用。但是,情况并非如此,特别是对于myArr
情况,如@vadian's answer中指出的那样,发出警告。在财产观察者中改变财产本身不会触发财产观察者这一事实并没有得到很好的证明,但是the Language Guide - Properties - Type Properties中的示例指出了这一点[强调我的]:>
查询和设置类型属性
willSet
属性有一个currentLevel
属性观察者可以检查
设置didSet
的值。 ... currentLevel
观察者设置
didSet
更改为其他值。 但这不会导致
再次调用观察者。 currentLevel
是合并例如边界检查将给定的属性值限制在一定范围内;也就是说,如果新值超出范围,则用有界值覆盖新值。didSet
答案 2 :(得分:1)
aAlan对didSet
和willSet
的评论很有趣。我尝试了相同的代码,但使用了didSet
,并且它已从数组中删除了最初看起来很奇怪的元素。我认为这是设计使然。我的理由是:
willSet
中获得了对实际项目本身的引用并进行了更改,则所有内容都会被覆盖。它使所有更改无效。因为您正在之前进行此操作,所以您甚至都阅读了即将发生的事情。另外(重复dfri所说的内容),如果再次在willSet
内设置它,则将再次触发属性观察器 ,并创建一个反馈循环,该循环将导致编译器,因此幕后的编译器didSet
来说不是一样。您等待...读取值,然后做出决定。您知道该属性的值。