[英]Swift didSet does not fire
Suppose I have class ExerciseSet with 3 properties: id, name, isEnabled. 假设我有一个具有3个属性的ExerciseSet类:id,name,isEnabled。
I have an array of objects of this class: 我有一个此类的对象数组:
var exerciseSets: [ExerciseSet] = [] {
didSet {
ExerciseSet.syncWithPList(updatedSets: exerciseSets)
}
}
Somewhere in the code I do the following: 在代码中的某处,我执行以下操作:
exerciseSets[index].isEnabled = !exerciseSets[index].isEnabled
But didSet would not fire in this case. 但是didSet在这种情况下不会触发。 Only if I write like this: 仅当我这样写时:
let set = exerciseSets[index]
set.isEnabled = !set.isEnabled
exerciseSets[index] = set
Why is it so? 为什么会这样呢? Can I somehow use the former option? 我可以以某种方式使用前一个选项吗? The latter one seems to verbose, I hate it. 后者似乎很冗长,我讨厌。
That is most probably because ExerciseSet
is a class, which means it is a reference type. 这很可能是因为ExerciseSet
是一个类,这意味着它是一个引用类型。
Just think of reference types variables as storing numbers. 只需将引用类型变量视为存储数字即可。 These numbers then point to where the actual ExerciseSet
is located in memory. 这些数字然后指向实际的ExerciseSet
在内存中的位置。 In other words [ExerciseSet]
is essentially an array of numbers. 换句话说, [ExerciseSet]
本质上是一个数字数组。
When you do this: 执行此操作时:
exerciseSets[index].isEnabled = !exerciseSets[index].isEnabled
You did not change any of the "numbers" in the array. 您没有更改数组中的任何“数字”。 You only looked for the "number" at a particular index, and you use that "number" to find the ExerciseSet
object. 您仅在特定索引中查找“数字”,然后使用该“数字”查找ExerciseSet
对象。 After that, you set a property of the ExerciseSet
. 之后,您设置了ExerciseSet
的属性。
As you can see, you did not modify the "number" in the array at all! 如您所见,您根本没有修改数组中的“数字”!
On the other hand, your second piece of code calls the didSet
because you're telling it to throw away the element at a particular index and put the "number" that points to set
at that index. 在另一方面,你的代码的第二条调用didSet
因为你告诉它,在一个特定的指数扔掉元素,并把指向“数量” set
该索引处。 Since you're tsking out an element of the array and putting something back in, you're changing the array itself! 由于您要设计数组的元素并放回一些东西,因此您要更改数组本身! Therefore, didSet
is called. 因此, didSet
被调用。
Hate is a strong word :) 仇恨是一个很强的词:)
In this line: 在这一行:
exerciseSets[index].isEnabled = !exerciseSets[index].isEnabled
you're not actually changing anything directly in your exerciseSets
array, you are changing something on a specific ExerciseSet
item in that array. 您实际上并没有直接在exerciseSets
数组中进行任何更改,而是在该数组中特定的 ExerciseSet
项目上进行了更改。
Compare that to: 比较一下:
let set = exerciseSets[index]
set.isEnabled = !set.isEnabled
exerciseSets[index] = set
Here you are changing an actual item in your exerciseSets
array and therefore didSet
is fired. 在这里,您正在更改exerciseSets
数组中的实际项 ,因此将触发didSet
。
Can you do something about it? 你能做些什么吗? Good question :) You need to update the exerciseSets
array in some way or another to force the didSet
so I don't think you can do it a lot shorter than the three lines above. 好问题:)您需要以某种方式更新exerciseSets
数组以强制didSet
因此我认为您不能比上述三行短很多。 I hope I am wrong though. 我希望我是错的。
Yeah, not so much an answer as a comment, hope you can use it anyway. 是的,与其说是评论,不如说是答案,希望您仍然可以使用它。
The didSet
trigger applies to the set, but not to its contents. didSet
触发器适用于集合,但不适用于其内容。 In other words, changing what objects are stored in the set triggers the block, but changing the objects' contents doesn't. 换句话说, 更改对象集中存储的对象将触发该块,但更改对象的内容则不会。 That's why your first option doesn't work and the second one does. 这就是为什么您的第一个选项不起作用而第二个选项却起作用的原因。
didSet
fires when you change value of the property , in example it would be when array itself changes. 当更改属性的值时, didSet
触发,例如,数组本身发生更改时。
Here 这里
exerciseSets[index].isEnabled = !exerciseSets[index].isEnabled
you change property of some object in the array, but array stays the same , and contains same objects. 您可以更改数组中某些对象的属性,但是数组保持不变 ,并且包含相同的对象。 So didSet
won't be called. 所以didSet
将不会被调用。
No, you can't. 不,你不能。 Use latter. 使用后者。
EDIT: I checked @martin-r advice to use structs for ExerciseSet
, and it works, didSet
set is called. 编辑:我检查了@ martin-r建议以使用ExerciseSet
结构,它的工作原理是调用didSet
设置。 Because when property value change for structure basically means creation of new structure with all but changed field being copied. 因为当结构的属性值更改时,基本上意味着要创建新结构,并复制所有更改的字段。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.