Pregunta
Los documentos de Apple especifican que:
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.
¿Es posible forzar que se invoquen estos durante la inicialización?
¿Por qué?
Digamos que tengo esta clase
class SomeClass {
var someProperty: AnyObject {
didSet {
doStuff()
}
}
init(someProperty: AnyObject) {
self.someProperty = someProperty
doStuff()
}
func doStuff() {
// do stuff now that someProperty is set
}
}
Creé el método doStuffpara hacer que las llamadas de procesamiento sean más concisas, pero prefiero simplemente procesar la propiedad dentro de la didSetfunción. ¿Hay alguna manera de forzar esto a llamar durante la inicialización?
Actualizar
Decidí eliminar el intializador de conveniencia para mi clase y forzarlo a configurar la propiedad después de la inicialización. Esto me permite saber didSetque siempre se llamará. No he decidido si esto es mejor en general, pero se adapta bien a mi situación.

defer:convenience init(someProperty: AnyObject) { self.init() defer { self.someProperty = someProperty }Respuestas:
Cree un método set propio y úselo dentro de su método init:
fuente
somePropertycomo tipo:AnyObject!(una opción implícitamente desenvuelta), permiteselfinicializar completamente sinsomePropertyestar configurado. Cuando llamassetSomeProperty(someProperty)estás llamando a un equivalente deself.setSomeProperty(someProperty). Normalmente no podría hacer esto porqueselfno se ha inicializado por completo. ComosomePropertyno requiere inicialización y está llamando a un método dependienteself, Swift deja el contexto de inicialización ydidSetse ejecutará.init() { *HERE* }habrá llamado a SetSet. Excelente para esta pregunta, pero el uso de una función secundaria para establecer algunos valores lleva a llamar a didSet. No es genial si quieres reutilizar esa función de configuración.Si se utiliza
deferdentro de un inicializador , para la actualización de las propiedades opcionales o más propiedades de actualización no opcionales que ya ha inicializado y después de que ha llamado a ningúnsuper.init()métodos, a continuación, suwillSet,didSetetc. será llamado. Creo que esto es más conveniente que implementar métodos separados que tiene que hacer un seguimiento de las llamadas en los lugares correctos.Por ejemplo:
Rendirá:
fuente
defer. Gracias.Como una variación de la respuesta de Oliver, podría ajustar las líneas en un cierre. P.ej:
Editar: la respuesta de Brian Westphal es mejor en mi humilde opinión. Lo bueno de él es que insinúa la intención.
fuente
Tuve el mismo problema y esto funciona para mí.
fuente
Esto funciona si haces esto en una subclase
Por
aejemplo,didSetno se activa. Pero, porbejemplo,didSetse dispara, porque está en la subclase. Tiene que ver con lo queinitialization contextrealmente significa, en este caso, esosuperclasssí le importófuente
Si bien esto no es una solución, una forma alternativa de hacerlo sería usar un constructor de clases:
fuente
somePropertyya que no le habrá dado un valor durante la inicialización.En el caso particular en el que desea invocar
willSetodidSetdentroinitde una propiedad disponible en su superclase, simplemente puede asignar su súper propiedad directamente:Tenga en cuenta que la solución de carlosismo con un cierre siempre funcionaría también en ese caso. Entonces mi solución es solo una alternativa.
fuente
Puedes resolverlo de forma obj-с:
fuente
self.someProperty, estás dejando el alcance de inicialización. Creo que lo mismo podría lograrse haciendovar someProperty: AnyObject! = nil { didSet { ... } }. Aún así, algunos podrían apreciarlo como una solución, gracias por la adición