Las muchas respuestas existentes bien escritas cubren bien la pregunta, pero mencionaré, con cierto detalle, una adición que creo que vale la pena cubrir.
Los observadores de propiedades willSet
y didSet
se pueden usar para llamar a delegados, por ejemplo, para propiedades de clase que solo se actualizan por interacción del usuario, pero donde desea evitar llamar al delegado en la inicialización del objeto.
Citaré el comentario votado de Klaas a la respuesta aceptada:
Los observadores willSet y didSet no son llamados cuando una propiedad se inicializa por primera vez. Solo se llaman cuando el valor de la propiedad se establece fuera de un contexto de inicialización.
Esto es bastante bueno, ya que significa, por ejemplo, que la didSet
propiedad es una buena opción de punto de inicio para delegar devoluciones de llamada y funciones, para sus propias clases personalizadas.
Como ejemplo, considere algún objeto de control de usuario personalizado, con alguna propiedad clave value
(por ejemplo, posición en el control de calificación), implementado como una subclase 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.
}
Después de lo cual sus funciones de delegado se pueden usar en, digamos, algún controlador de vista para observar los cambios clave en el modelo CustomViewController
, al igual que usaría las funciones de delegado inherentes de los objetos UITextFieldDelegate
for UITextField
(por ejemplo textFieldDidEndEditing(...)
).
Para este ejemplo simple, use una devolución de llamada delegada didSet
de la propiedad de la clase value
para decirle a un controlador de vista que una de sus salidas ha tenido una actualización de modelo asociada:
// 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 ...
//}
}
Aquí, la value
propiedad se ha encapsulado, pero en general: en situaciones como estas, tenga cuidado de no actualizar la value
propiedad del customUserControl
objeto en el ámbito de la función delegada asociada (aquí:) didChangeValue()
en el controlador de vista, o terminará con recursión infinita
get
&set
) básicamente consiste en calcular una propiedad basada en otra propiedad, por ejemplo, convertir una etiquetatext
en un añoInt
.didSet
ywillSet
estamos ahí para decir ... hey, este valor se estableció, ahora hagamos esto, por ejemplo, Nuestro dataSource se actualizó ... así que volvamos a cargar el TableView para que incluya nuevas filas. Para otro ejemplo, vea la respuesta de dfri sobre cómo llamar a los delegados endidSet