Captadores y establecedores de propiedades

Con esta clase simple recibo la advertencia del comstackdor

Intentando modificar / acceder a x dentro de su propio setter / getter

y cuando lo uso así:

 var p: point = Point() px = 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 } } // ... } 

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 / 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 .

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.

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 } } ... 

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 statement de la variable.

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 

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.


La regla del pulgar es nunca acceder a la propiedad desde el getter, es decir, get . Porque eso dispararía otro get que dispararía otro. . . Ni siquiera lo imprima. ¡Porque la impresión también requiere ‘obtener’ el valor antes de poder imprimirlo!

 struct Person{ var name: String{ get{ print(name) // DON'T do this!!!! return "as" } set{ } } } let p1 = Person() 

Como eso daría la siguiente advertencia:

Intentando acceder a ‘nombre’ desde su propio getter.

El error parece vago así:

enter image description here

Como alternativa, es posible que desee utilizar didSet . Con didSet obtendrá una retención del valor que se configuró antes y acaba de configurar. Para más ver esta respuesta .

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.

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 

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 .

Aquí hay una respuesta teórica. Eso se puede encontrar aquí

Una propiedad {get set} no puede ser una propiedad almacenada constante. Debe ser una propiedad calculada y tanto get como set deben implementarse.

    Intereting Posts