简体   繁体   English

Swift didSet不会触发

[英]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. 这就是为什么您的第一个选项不起作用而第二个选项却起作用的原因。

Why is it so? 为什么会这样呢?

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将不会被调用。

Can I somehow use the former option? 我可以以某种方式使用前一个选项吗?

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.

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