will through setters paths lazy itself getters example and all swift properties compiler-warnings getter-setter

through - properties swift



Captadores y establecedores de propiedades (9)

Actualización: Swift 4

En el setter y getter de clase inferior se aplica a sideLength variable

class Triangle: { var sideLength: Double = 0.0 init(sideLength: Double, name: String) { //initializer method self.sideLength = sideLength super.init(name: name) numberOfSides = 3 } var perimeter: Double { get { // getter return 3.0 * sideLength } set { //setter sideLength = newValue / 4.0 } }

Creando un objeto

var triangle = Triangle(sideLength: 3.9, name: "a triangle")

Adquiridor

print(triangle.perimeter) // invoking getter

Setter

triangle.perimeter = 9.9 // invoking setter

Con esta clase simple recibo la advertencia del compilador "Intentando modificar / acceder a ''x'' dentro de su propio setter / getter" y cuando lo uso así:

var p: point = Point() p.x = 12

Obtengo un EXC_BAD_ACCESS. ¿Cómo puedo hacer esto sin ivars de respaldo explícitos?

class Point { var x: Int { set { x = newValue * 2 //Error } get { return x / 2 //Error } } // ... }


Estás definiendo recursivamente x con x . Como si alguien te preguntara ¿cuántos años tienes? Y respondes "Tengo el doble de mi edad". Que no tiene sentido

Debes decir que tengo el doble de la edad de John o cualquier otra variable que no seas tú mismo.

las variables calculadas siempre dependen de otra variable.


Intenta usar esto:

var x:Int! var xTimesTwo:Int { get { return x * 2 } set { x = newValue / 2 } }

Esta es básicamente la respuesta de Jack Wu, pero la diferencia es que en la respuesta de Jack Wu su variable x es var x: Int , en el mío, mi variable x es así: var x: Int! , así que todo lo que hice fue convertirlo en un tipo opcional.


Para anular setter y getter para variables rápidas, use el siguiente código

var temX : Int? var x: Int?{ set(newX){ temX = newX } get{ return temX } }

Necesitamos mantener el valor de la variable en una variable temporal, ya que intentar acceder a la misma variable cuyo getter / setter se está anulando dará como resultado bucles infinitos.

Podemos invocar al colocador simplemente así

x = 10

Getter se invocará al disparar debajo de la línea de código dada

var newVar = x


Para profundizar en la respuesta de GoZoner:

Su verdadero problema aquí es que está llamando recursivamente a su getter.

var x:Int { set { x = newValue * 2 // This isn''t a problem } get { return x / 2 // Here is your real issue, you are recursively calling // your x property''s getter } }

Al igual que el comentario del código sugiere más arriba, está llamando infinitamente al captador de la propiedad x, que continuará ejecutándose hasta que obtenga un código EXC_BAD_ACCESS (puede ver el rotador en la esquina inferior derecha del entorno de recreo de su Xcode).

Considere el ejemplo de la documentación de Swift :

struct Point { var x = 0.0, y = 0.0 } struct Size { var width = 0.0, height = 0.0 } struct AlternativeRect { var origin = Point() var size = Size() var center: Point { get { let centerX = origin.x + (size.width / 2) let centerY = origin.y + (size.height / 2) return Point(x: centerX, y: centerY) } set { origin.x = newValue.x - (size.width / 2) origin.y = newValue.y - (size.height / 2) } } }

Observe cómo la propiedad calculada del centro nunca se modifica o se devuelve en la declaración de la variable.


Puede personalizar el valor establecido utilizando el observador de propiedades. Para hacer esto, use ''didSet'' en lugar de ''set''.

class point { var x:Int { didSet { x = x * 2 } } ...

En cuanto a getter ...

class point { var doubleX:Int { get { return x / 2 } } ...


Setters y Getters se aplican a las computed properties ; tales propiedades no tienen almacenamiento en la instancia; el valor del captador debe calcularse a partir de otras propiedades de instancia. En su caso, no hay x para ser asignado.

Explícitamente: "¿Cómo puedo hacer esto sin ivars de respaldo explícitos". No puede: necesitará algo para hacer una copia de seguridad de la propiedad calculada. Prueba esto:

class Point { private var _x: Int = 0 // _x -> backingX var x: Int { set { _x = 2 * newValue } get { return _x / 2 } } }

Específicamente, en el REPL de Swift:

15> var pt = Point() pt: Point = { _x = 0 } 16> pt.x = 10 17> pt $R3: Point = { _x = 20 } 18> pt.x $R4: Int = 10


Setters y getters en Swift se aplican a las propiedades / variables calculadas. Estas propiedades / variables no se almacenan realmente en la memoria, sino que se calculan en función del valor de las propiedades / variables almacenadas.

Consulte la documentación de Apple sobre el tema Swift Variable Declarations .


EDITAR : Dado que esta respuesta es obtener algunos votos favorables, me gustaría aclarar que setters / getters en Swift son bastante diferentes a ObjC. La propiedad se convierte en una propiedad calculada, lo que significa que no tiene una variable de respaldo como _x como lo haría en ObjC. En el código de la solución a continuación, puede ver que xTimesTwo no almacena nada, sino que simplemente calcula el resultado de x .

Ver Documentos oficiales en propiedades calculadas .

La funcionalidad que desea también puede ser Property Observers .

Setters / getters son diferentes de lo que eran en Objective-C.

Lo que necesitas es:

var x:Int var xTimesTwo:Int { set { x = newValue / 2 } get { return x * 2 } }

Puede modificar otras propiedades dentro del setter / getters, que es para lo que están diseñadas.