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 doStuff
para hacer que las llamadas de procesamiento sean más concisas, pero prefiero simplemente procesar la propiedad dentro de la didSet
funció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 didSet
que 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
someProperty
como tipo:AnyObject!
(una opción implícitamente desenvuelta), permiteself
inicializar completamente sinsomeProperty
estar configurado. Cuando llamassetSomeProperty(someProperty)
estás llamando a un equivalente deself.setSomeProperty(someProperty)
. Normalmente no podría hacer esto porqueself
no se ha inicializado por completo. ComosomeProperty
no requiere inicialización y está llamando a un método dependienteself
, Swift deja el contexto de inicialización ydidSet
se 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
defer
dentro 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
,didSet
etc. 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
a
ejemplo,didSet
no se activa. Pero, porb
ejemplo,didSet
se dispara, porque está en la subclase. Tiene que ver con lo queinitialization context
realmente significa, en este caso, esosuperclass
sí le importófuente
Si bien esto no es una solución, una forma alternativa de hacerlo sería usar un constructor de clases:
fuente
someProperty
ya que no le habrá dado un valor durante la inicialización.En el caso particular en el que desea invocar
willSet
odidSet
dentroinit
de 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