Les nombreuses réponses existantes bien écrites couvrent bien la question, mais je mentionnerai, en détail, un ajout qui, je crois, mérite d'être couvert.
Les observateurs de propriétés willSetet didSetpeuvent être utilisés pour appeler des délégués, par exemple, pour des propriétés de classe qui ne sont jamais mises à jour que par interaction de l'utilisateur, mais où vous voulez éviter d'appeler le délégué lors de l'initialisation de l'objet.
Je citerai le commentaire voté par Klaas à la réponse acceptée:
Les observateurs willSet et didSet ne sont pas appelés lors de la première initialisation d'une propriété. Ils ne sont appelés que lorsque la valeur de la propriété est définie en dehors d'un contexte d'initialisation.
Ceci est assez soigné car cela signifie par exemple que la didSetpropriété est un bon choix de point de lancement pour les fonctions et rappels délégués, pour vos propres classes personnalisées.
Par exemple, considérons un objet de contrôle utilisateur personnalisé, avec une propriété clé value(par exemple, la position dans le contrôle de notation), implémenté comme une sous-classe de UIView:
// CustomUserControl.swift
protocol CustomUserControlDelegate {
func didChangeValue(value: Int)
// func didChangeValue(newValue: Int, oldValue: Int)
// func didChangeValue(customUserControl: CustomUserControl)
// ... other more sophisticated delegate functions
}
class CustomUserControl: UIView {
// Properties
// ...
private var value = 0 {
didSet {
// Possibly do something ...
// Call delegate.
delegate?.didChangeValue(value)
// delegate?.didChangeValue(value, oldValue: oldValue)
// delegate?.didChangeValue(self)
}
}
var delegate: CustomUserControlDelegate?
// Initialization
required init?(...) {
// Initialise something ...
// E.g. 'value = 1' would not call didSet at this point
}
// ... some methods/actions associated with your user control.
}
Après quoi, vos fonctions de délégué peuvent être utilisées dans, disons, certains contrôleurs de vue pour observer les changements clés dans le modèle CustomViewController, tout comme vous utiliseriez les fonctions de délégué inhérentes UITextFieldDelegateaux UITextFieldobjets for (par exemple textFieldDidEndEditing(...)).
Pour cet exemple simple, utilisez un rappel délégué à partir didSetde la propriété de classe valuepour indiquer à un contrôleur de vue que l'une de ses sorties a eu une mise à jour de modèle associée:
// ViewController.swift
Import UIKit
// ...
class ViewController: UIViewController, CustomUserControlDelegate {
// Properties
// ...
@IBOutlet weak var customUserControl: CustomUserControl!
override func viewDidLoad() {
super.viewDidLoad()
// ...
// Custom user control, handle through delegate callbacks.
customUserControl = self
}
// ...
// CustomUserControlDelegate
func didChangeValue(value: Int) {
// do some stuff with 'value' ...
}
// func didChangeValue(newValue: Int, oldValue: Int) {
// do some stuff with new as well as old 'value' ...
// custom transitions? :)
//}
//func didChangeValue(customUserControl: CustomUserControl) {
// // Do more advanced stuff ...
//}
}
Ici, la valuepropriété a été encapsulée, mais généralement: dans des situations comme celles-ci, veillez à ne pas mettre à jour la valuepropriété de l' customUserControlobjet dans la portée de la fonction déléguée associée (ici:) didChangeValue()dans le contrôleur de vue, ou vous vous retrouverez avec récursion infinie.
get&set) doit essentiellement avoir une propriété calculée sur la base d'une autre propriété, par exemple la conversion d'une étiquettetexten une annéeInt.didSet&willSetsont là pour dire ... hé cette valeur a été définie, maintenant faisons ceci par exemple Notre dataSource a été mise à jour ... alors rechargeons la tableView afin qu'elle inclue de nouvelles lignes. Pour un autre exemple, voir la réponse de dfri sur la façon d'appeler les déléguésdidSet