繁体   English   中英

Swift didSet不会触发

[英]Swift didSet does not fire

假设我有一个具有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

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

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

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

执行此操作时:

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

您没有更改数组中的任何“数字”。 您仅在特定索引中查找“数字”,然后使用该“数字”查找ExerciseSet对象。 之后,您设置了ExerciseSet的属性。

如您所见,您根本没有修改数组中的“数字”!

在另一方面,你的代码的第二条调用didSet因为你告诉它,在一个特定的指数扔掉元素,并把指向“数量” set该索引处。 由于您要设计数组的元素并放回一些东西,因此您要更改数组本身! 因此, didSet被调用。

仇恨是一个很强的词:)

在这一行:

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

您实际上并没有直接exerciseSets数组中进行任何更改,而是在该数组中特定的 ExerciseSet项目上进行更改。

比较一下:

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

在这里,您正在更改exerciseSets数组中的实际项 ,因此将触发didSet

你能做些什么吗? 好问题:)您需要以某种方式更新exerciseSets数组以强制didSet因此我认为您不能比上述三行短很多。 我希望我是错的。

是的,与其说是评论,不如说是答案,希望您仍然可以使用它。

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

为什么会这样呢?

当更改属性的值时, didSet触发,例如,数组本身发生更改时。

这里

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

您可以更改数组中某些对象的属性,但是数组保持不变 ,并且包含相同的对象。 所以didSet将不会被调用。

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

不,你不能。 使用后者。

编辑:我检查了@ martin-r建议以使用ExerciseSet结构,它的工作原理是调用didSet设置。 因为当结构的属性值更改时,基本上意味着要创建新结构,并复制所有更改的字段。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM