Swift tiene una sintaxis de declaración de propiedad muy similar a la de C #:
var foo: Int {
get { return getFoo() }
set { setFoo(newValue) }
}
Sin embargo, también tiene willSet
y didSet
acciones. Estos se llaman antes y después de llamar al setter, respectivamente. ¿Cuál es su propósito, teniendo en cuenta que podría tener el mismo código dentro del setter?
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
Respuestas:
El punto parece ser que a veces, necesita una propiedad que tenga almacenamiento automático y algún comportamiento, por ejemplo, para notificar a otros objetos que la propiedad acaba de cambiar. Cuando todo lo que tiene es
get
/set
, necesita otro campo para mantener el valor. ConwillSet
ydidSet
, puede tomar medidas cuando se modifica el valor sin necesidad de otro campo. Por ejemplo, en ese ejemplo:myProperty
imprime su valor antiguo y nuevo cada vez que se modifica. Con solo getters y setters, necesitaría esto en su lugar:Así
willSet
ydidSet
representar una economía de un par de líneas, y menos ruido en la lista de campos.fuente
willSet
ydidSet
no se llama cuando configura la propiedad desde un método init como Apple observa:willSet and didSet observers are not called when a property is first initialized. They are only called when the property’s value is set outside of an initialization context.
myArrayProperty.removeAtIndex(myIndex)
... No se espera.Entiendo que set y get son para propiedades calculadas (sin respaldo de propiedades almacenadas )
si viene de un Objective-C, tenga en cuenta que las convenciones de nomenclatura han cambiado. En Swift, una variable iVar o instancia se denomina propiedad almacenada
Ejemplo 1 (propiedad de solo lectura) - con advertencia:
Esto dará como resultado una advertencia porque esto dará como resultado una llamada de función recursiva (el getter se llama a sí mismo). La advertencia en este caso es "Intentar modificar 'prueba' dentro de su propio getter".
Ejemplo 2. Lectura / escritura condicional - con advertencia
Problema similar: no puede hacer esto ya que llama de forma recursiva al setter. Además, tenga en cuenta que este código no se quejará de que no hay inicializadores, ya que no hay propiedades almacenadas para inicializar .
Ejemplo 3. propiedad calculada de lectura / escritura - con almacén de respaldo
Aquí hay un patrón que permite la configuración condicional de una propiedad almacenada real
Nota Los datos reales se denominan _test (aunque podría ser cualquier dato o combinación de datos). Tenga en cuenta también la necesidad de proporcionar un valor inicial (alternativamente, debe usar un método init) porque _test es en realidad una variable de instancia
Ejemplo 4. Usando will y did set
Aquí vemos willSet y didSet interceptando un cambio en una propiedad almacenada real. Esto es útil para enviar notificaciones, sincronización, etc. (ver ejemplo a continuación)
Ejemplo 5. Ejemplo concreto: Contenedor ViewController
Tenga en cuenta el uso de AMBAS propiedades calculadas y almacenadas. He usado una propiedad calculada para evitar establecer el mismo valor dos veces (¡para evitar que sucedan cosas malas!); He usado willSet e didSet para reenviar notificaciones a viewControllers (consulte la documentación e información de UIViewController en los contenedores de viewController)
¡Espero que esto ayude, y por favor alguien grite si he cometido un error en algún lugar aquí!
fuente
//I can't see a way to 'stop' the value being set to the same controller - hence the computed property
advertencia desaparece después de usar enif let newViewController = _childVC {
lugar deif (_childVC) {
get
, creo que necesita agregarif _childVC == nil { _childVC = something }
y luegoreturn _childVC
.Estos se llaman Observadores de propiedades :
Extracto de: Apple Inc. "El lenguaje de programación Swift". iBooks https://itun.es/ca/jEUH0.l
Sospecho que es para permitir cosas que tradicionalmente haríamos con KVO , como el enlace de datos con elementos de la interfaz de usuario, o desencadenar efectos secundarios de cambiar una propiedad, desencadenar un proceso de sincronización, procesamiento en segundo plano, etc.
fuente
fuente
También puede usar el
didSet
para establecer la variable en un valor diferente. Esto no hace que se vuelva a llamar al observador como se indica en la guía de propiedades . Por ejemplo, es útil cuando desea limitar el valor de la siguiente manera:fuente
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
ydidSet
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:
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 deUIView
: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 objetosUITextFieldDelegate
forUITextField
(por ejemplotextFieldDidEndEditing(...)
).Para este ejemplo simple, use una devolución de llamada delegada
didSet
de la propiedad de la clasevalue
para decirle a un controlador de vista que una de sus salidas ha tenido una actualización de modelo asociada:Aquí, la
value
propiedad se ha encapsulado, pero en general: en situaciones como estas, tenga cuidado de no actualizar lavalue
propiedad delcustomUserControl
objeto en el ámbito de la función delegada asociada (aquí:)didChangeValue()
en el controlador de vista, o terminará con recursión infinitafuente
Y tenga en cuenta que
willSet
necesita un nombre de parámetro para evitar, por otro lado,didSet
no.fuente
Getter y setter a veces son demasiado pesados para implementar solo para observar los cambios de valor adecuados. Por lo general, esto requiere un manejo variable temporal adicional y controles adicionales, y querrá evitar incluso esa pequeña mano de obra si escribe cientos de captadores y establecedores. Estas cosas son para la situación.
fuente
willSet
ydidSet
contra el código de establecimiento equivalente? Esto parece una afirmación audaz.En su propia clase (base),
willSet
ydidSet
son bastante redundantes , ya que en su lugar podría definir una propiedad calculada (es decir, métodos get y set ) que acceden ay_propertyVariable
hacen el pre y post prospeso deseado .Si, sin embargo , se reemplaza una clase donde la propiedad está ya definido , entonces el
willSet
ydidSet
son útiles y no redundante!fuente
Una cosa que
didSet
es realmente útil es cuando usa puntos de venta para agregar configuración adicional.fuente
No sé C #, pero con un poco de conjeturas creo que entiendo qué
hace. Se ve muy similar a lo que tiene en Swift, pero no es lo mismo: en Swift no tiene el
getFoo
ysetFoo
. Esa no es una pequeña diferencia: significa que no tiene ningún almacenamiento subyacente para su valor.Swift ha almacenado y calculado propiedades.
Una propiedad calculada tiene
get
y puede tenerset
(si se puede escribir). Pero el código en getter y setter, si necesitan almacenar algunos datos, debe hacerlo en otras propiedades. No hay almacenamiento de respaldo.Una propiedad almacenada, por otro lado, tiene almacenamiento de respaldo. Pero no tiene
get
yset
. En cambio, sí,willSet
ydidSet
puede usarlo para observar cambios variables y, eventualmente, desencadenar efectos secundarios y / o modificar el valor almacenado. No tienewillSet
ydidSet
para propiedades calculadas, y no las necesita porque para propiedades calculadas puede usar el códigoset
para controlar los cambios.fuente
getFoo
ysetFoo
son simples marcadores de posición para lo que quiera que hagan los captadores y establecedores. C # tampoco los necesita. (