web-dev-qa-db-fra.com

Dans Swift, la réinitialisation de la propriété dans didSet déclenche-t-elle un autre didSet?

Je teste ceci et il semble que si vous modifiez la valeur dans didSet, vous ne recevez pas un autre appel à didSet

var x: Int = 0 {
    didSet {
        if x == 9 { x = 10 }
    }
}

Puis-je compter sur cela? Est-ce documenté quelque part? Je ne le vois pas dans le Swift Programming Language document.

13
Rob N

J'ai aussi pensé que ce n'était pas possible (peut-être que ce n'était pas dans Swift 2), mais je l'ai testé et trouvé un exemple où Apple l'utilise. (Dans "Interrogation et définition des propriétés de type")

struct AudioChannel {
    static let thresholdLevel = 10
    static var maxInputLevelForAllChannels = 0
    var currentLevel: Int = 0 {
        didSet {
            if currentLevel > AudioChannel.thresholdLevel {
                // cap the new audio level to the threshold level
                currentLevel = AudioChannel.thresholdLevel
            }
            if currentLevel > AudioChannel.maxInputLevelForAllChannels {
                // store this as the new overall maximum input level
                AudioChannel.maxInputLevelForAllChannels = currentLevel
            }
        }
    }
}

Et en dessous de ce morceau de code, il y a la note suivante:

Dans la première de ces deux vérifications, l'observateur didSet attribue à currentLevel une valeur différente. Ceci ne, cependant, ne provoque pas l'appel de l'observateur à nouveau.

14
FelixSFD

D'après les documents Apple (c'est moi qui souligne): 

De même, si vous implémentez un observateur didSet, il passe une constante paramètre contenant l'ancienne valeur de la propriété. Vous pouvez nommer le paramètre ou utilisez le nom de paramètre par défaut de oldValue. Si vous attribuer une valeur à une propriété dans son propre observateur didSet, le nouveau La valeur que vous affectez remplace celle qui vient d'être définie.

Donc, assigner une valeur dans didSet est officiellement OK et ne déclenchera pas une récursion infinie.

4
FreeNickname

Cela fonctionnera très bien, mais cela semble être une assez mauvaise idée du point de vue du consommateur de votre API.

Cela ne récidive pas, comme je le pensais, alors c'est bien au moins.

Je peux penser à quelques cas dans lesquels il serait acceptable pour un passeur de changer ce que je suis en train de régler. Un exemple de ce type pourrait être une variable définie sur un angle, automatiquement normalisée sur [0, 2π].

1
Alexander