Swift didSet不会开火

时间:2016-11-16 07:45:23

标签: swift computed-properties didset

假设我有一个具有3个属性的ExerciseSet类:id,name,isEnabled。

我有这个类的对象数组:

var exerciseSets: [ExerciseSet] = [] {
    didSet {
        ExerciseSet.syncWithPList(updatedSets: exerciseSets)
    }
}

代码中的某处我执行以下操作:

exerciseSets[index].isEnabled = !exerciseSets[index].isEnabled

但是在这种情况下didSet不会触发。只有我这样写:

let set = exerciseSets[index]
set.isEnabled = !set.isEnabled
exerciseSets[index] = set

为什么会这样?我可以以某种方式使用前一个选项吗?后者似乎很冗长,我讨厌它。

4 个答案:

答案 0 :(得分:2)

这很可能是因为ExerciseSet是一个类,这意味着它是一个引用类型。

只需将引用类型变量视为存储数字即可。然后,这些数字指向实际ExerciseSet位于内存中的位置。换句话说,[ExerciseSet]本质上是一个数字数组。

执行此操作时:

exerciseSets[index].isEnabled = !exerciseSets[index].isEnabled

您没有更改任何"数字"在数组中。你只找了"号码"在特定的索引处,您使用" number"找到ExerciseSet对象。之后,您设置了ExerciseSet

的属性

正如您所看到的,您没有修改"数字"在阵列中!

另一方面,你的第二段代码会调用didSet,因为你要告诉它将元素丢弃在特定的索引处,然后输入"数字"指向该指数的set。既然您正在搜索阵列中的某个元素并重新放入某些内容,那么您就可以更改阵列本身!因此,didSet被调用。

答案 1 :(得分:1)

仇恨是一个强有力的词:)

在这一行:

exerciseSets[index].isEnabled = !exerciseSets[index].isEnabled

您实际上并未在exerciseSets数组中直接更改 中的任何内容,而是在特定 ExerciseSet项目中更改某些内容那个阵列。

将其与:

进行比较
let set = exerciseSets[index]
set.isEnabled = !set.isEnabled
exerciseSets[index] = set

您要在exerciseSets数组中更改实际项目,因此会didSet被解雇。

你能做些什么吗?好问题:)你需要以某种方式更新exerciseSets数组以强制didSet,所以我不认为你可以比上面的三行短得多。我希望我错了。

是的,不是作为评论的答案,希望你无论如何都可以使用它。

答案 2 :(得分:0)

didSet触发器适用于集合,但不适用于其内容。换句话说,更改集合中存储的对象会触发块,但更改对象的内容则不会。这就是为什么你的第一个选项不起作用而第二个选项不起作用的原因。

答案 3 :(得分:0)

为什么会这样?

更改属性值时会发生

didSet,例如,当数组本身发生更改时会发生这种情况。

下面

exerciseSets[index].isEnabled = !exerciseSets[index].isEnabled

更改数组中某个对象的属性,但数组保持不变,并包含相同的对象。因此didSet不会被召唤。

我可以以某种方式使用前一个选项吗?

不,你不能。使用后者。

编辑:我检查了@ martin-r建议使用ExerciseSet的结构,并且它有效,didSet set被调用。因为当结构的属性值改变时,基本上意味着创建新的结构,而只有被改变的字段被复制。