Las propiedades con observadores (property observers) en Swift permiten reaccionar a los cambios en el valor de una propiedad. Este concepto apareció junto con Swift para aumentar la transparencia en el control de cambios de datos y automatizar la lógica al realizar modificaciones.
Historia de la pregunta:
Antes de Swift, este comportamiento a menudo se implementaba manualmente a través de setters o métodos especiales. En Swift, los observadores se introdujeron como una herramienta estándar en el lenguaje.
Problema:
Es importante para el desarrollador poder detectar el momento en que cambia una propiedad, por ejemplo, para actualizar la interfaz de usuario o validar datos. Sin observadores, el código se volvería más pesado y menos legible.
Solución:
En Swift, hay dos observadores principales disponibles:
willSet se llama antes de cambiar el valordidSet se llama después de asignar un nuevo valorLos observadores se pueden agregar a stored properties, excepto propiedades lazy y propiedades computadas (computed).
Ejemplo de código:
class Temperature { var celsius: Double { willSet { print("Pronto se establecerá el valor", newValue) } didSet { print("El valor era:", oldValue, ", y ahora es:", celsius) } } init(celsius: Double) { self.celsius = celsius } } let temp = Temperature(celsius: 22) temp.celsius = 28 // Se imprimirá willSet y didSet
Características clave:
¿Se pueden agregar observadores a las propiedades computadas?
No, a las propiedades computadas no se les pueden agregar willSet y didSet, ya que ya tienen su propio getter y setter. El uso de willSet/didSet es relevante solo para las propiedades almacenadas.
¿Se llamarán los observadores al cambiar la propiedad dentro del inicializador?
No, los property observers no se llaman durante la inicialización (init). Se activan solo al cambiar el valor después de que se complete init.
¿Qué ocurrirá al asignar el valor actual a sí mismo, por ejemplo, x = x?
Los observadores aún se llamarán, ¡incluso si el valor de la propiedad no ha cambiado! Esto puede llevar a la ejecución inesperada de la lógica; ¡tenga cuidado!
var value: Int = 0 { didSet { print("didSet siempre se llama!") } } value = value // didSet se llamará
Un desarrollador implementó la actualización de la interfaz en didSet, pero no controló el cambio de valor. La interfaz de usuario se actualizaba incluso por un asignación “vacía”, lo que afectó el rendimiento.
Ventajas:
Desventajas:
En didSet se verificaba la igualdad entre el viejo y el nuevo valor. La actualización de la interfaz ocurría solo si el valor realmente cambiaba.
Ventajas:
Desventajas: