Preparación del sistema para crear suscripciones KVO
Para usar KVO en el código de Swift se requiere:
- La clase herede de
NSObject, - Marcar las propiedades que quiero que sean observables con
@objc dynamic, para que el compilador de Swift mantenga el runtime de Objective-C y no haga ninguna optimización (como hacerlo estático o inline).
Una vez activo el KVO en una propiedad, se puede crear un Publisher de Combine sobre ella con el método publisher(for: options:) (que no está documentado), que emite uno o dos valores, cada vez que se modifica la propiedad, dependiendo de las opciones que se hayan pasado por argumento que pueden ser .initial (emite el valor inicial junto con todos los cambios que haya después), .prior (cuando hay un cambio, emite el valor anterior y luego el nuevo valor) y .new y .old (ambos re-emiten el nuevo valor de la propiedad observada). Por defecto, las opciones son [.initial].
class TestObject: NSObject {
@objc dynamic var integerProperty: Int = 0
}
let obj = TestObject()
let subscription = obj.publisher(for: \.integerProperty)
.sink {
print("integerProperty changes to \($0)")
}
obj.integerProperty = 100
obj.integerProperty = 200
// integerProperty changes to 0 -> Hay una emisión cuando ocurre la suscripción
// integerProperty changes to 100
// integerProperty changes to 200
ObservableObject
Un ObservableObject es un tipo de dato que emite antes de que el objeto cambie. Toda clase que conforme este protocolo auto-sintetizará una propiedad llamada objectWillChange, que emite Void cada vez que alguna de las propiedades de la clase marcada con el wrapper @Published cambia (y nunca emite falla). Lo anterior también implica que un cambio de alguna propiedad que no tiene @Published, no provocará que el objectWillChange no emita ningún valor.
class Contact: ObservableObject {
@Published var age: Int
init(age: Int) {
self.age = age
}
func haveBirthday() -> Int {
age += 1
return age
}
}
let john = Contact(age: 24)
cancellable = john.objectWillChange
.sink { _ in print("\(john.age) will change") }
print(john.haveBirthday())
// Prints "24 will change"
// Prints "25"
Cuestionario
1. ¿Qué requisito debe cumplir una clase en Swift para usar KVO (Key-Value Observing)?
- [ ] Implementar el protocolo
ObservableObject - [ ] Heredar de
NSObject - [ ] Declarar todas las propiedades con
@Published - [ ] Usar
@objcMembersen la clase
2. ¿Para qué sirve el modificador @objc dynamic en una propiedad observada con KVO?
- [ ] Permite que Combine la observe automáticamente sin heredar de NSObject
- [ ] Indica que la propiedad se debe observar solo en Swift puro
- [ ] Evita que el compilador optimice la propiedad y mantiene el runtime de Objective-C
- [ ] Hace que la propiedad sea de solo lectura
3. ¿Qué opción del método publisher(for:options:) hace que el Publisher emita el valor actual de la propiedad al momento de la suscripción?
- [ ]
.prior - [ ]
.old - [ ]
.new - [ ]
.initial
4. En el protocolo ObservableObject, ¿qué emite la propiedad objectWillChange?
- [ ] El valor nuevo de cada propiedad observada
- [ ] El valor anterior de cada propiedad observada
- [ ] Un valor de tipo Void antes de que cambie cualquier propiedad
- [ ] Un error cuando la propiedad cambia
Solución
1. ¿Qué requisito debe cumplir una clase en Swift para usar KVO (Key-Value Observing)?
- [✅] Heredar de NSObject
2. ¿Para qué sirve el modificador @objc dynamic en una propiedad observada con KVO?
- [✅] Evita que el compilador optimice la propiedad y mantiene el runtime de Objective-C
3. ¿Qué opción del método publisher(for:options:) hace que el Publisher emita el valor actual de la propiedad al momento de la suscripción?
- [✅] .initial
4. En el protocolo ObservableObject, ¿qué emite la propiedad objectWillChange?
- [✅] Un valor de tipo
Voidantes de que cambie cualquier propiedad marcada con el property wrapper@Published
Top comments (0)