Tutorial Swift - Propiedades en Swift (Aprende a programar apps para iOS)
Tutorial Swift - Propiedades en Swift (Aprende a programar apps para iOS)

PROPIEDADES en Swift en Español - Curso Swift | Tutorial Swift

Las propiedades en Swift no solo almacenan variables o constantes. En este posts verás los tipos de propiedades que podemos usar en Swift: Computed Properties, Property Observers y Property Wrappers. A parte de Propiedades de Instancia y Propiedades de Tipo

SwiftBeta

Tabla de contenido


👇 SÍGUEME PARA APRENDER SWIFTUI, SWIFT, XCODE, etc 👇
Aprende Swift desde cero

Las propiedades de una instancia son propiedades que pertenecen a la instancia de un tipo en particular y las propiedades de tipo pertenecen al tipo y no a la instancia, un poco confuso pero en el siguiente ejemplo se ve muy claro:

struct User {
    var name: String
    static var brand: String = "SwiftBeta"
}

let user = User(name: "SwiftBeta")
user.name // Propiedad de instancia
User.brand // Propiedad de Tipo

En este caso, para poder acceder a la propiedad name tenemos que crear una instancia del tipo User. Pero si queremos acceder a la propiedad brand, no necesitamos ninguna instancia, nos bastaría poner el tipo seguido de la propiedad.

Cuando usamos clases y queremos una propiedad de tipo, podemos usar static o class. La diferencia entre static y class es que Si usamos class podemos hacer override al heredar de una clase.

Propiedades Computadas en Swift - Computed Properties

Estas propiedades no almacenan un valor, sino que actuan de getter y de setter. Vamos a ver un ejemplo:

struct Square {
    var origin: CGPoint = .zero
    var size: CGSize = .zero

    var center: CGPoint {
        get {
            let centerX = origin.x + (size.width * 0.5)
            let centerY = origin.y + (size.height * 0.5)
            return CGPoint(x: centerX, y: centerY)
        }
        set(newCenter) {
            origin.x = newCenter.x - (size.width * 0.5)
            origin.y = newCenter.y - (size.height * 0.5)
        }
    }
}

let square = Square(origin: .zero,
                    size: .init(width: 200, height: 200))

square.center

En el snippet de código hemos creado un struct llamado Square que tiene una variable computada que calcula el punto exacto de su centro. Esta variable no almacena nada, dentro de ella hay un get y un set con lógica.


Observadores de Propiedad - Property Observers

Podemos observar y responder cada vez que un valor de una propiedad cambia con los Property Observers

Podemos añadir observadores en:

  • Propiedades que hemos definido
  • Propiedades que hemos heredado
  • Propiedades Computadas que hemos heredado

Puedes usar los siguientes observadores en una propiedad:

  • willSet es llamado antes de que el valor sea guardado en la variable.
  • didSet es llamado inmediatamente después de almacenar el valor en la variable.

Al utilizar willSet, dentro de su scope puedes usar la variable newValue. Este valor será el que se almacenará en la variable.

newValue es el nombre por defecto cuando no hemos especificado ninguno. Podemos dar un nombre propio, en el siguiente ejemplo le hemos dado el nombre newName:

struct Database {
    var name: String {
        willSet(newName) {
            print("About to set name \(newName)")
        }
        
        didSet {
            print("Added \(name)")
        }
    }
}

var database = Database(name: "SwiftBeta")
database.name = "Infinito"

Los mensajes que se printan por consola son:

1. "About to set name Infinito"
2. "Added Infinito"

Ninguna sorpresa, todo tal y como esperábamos.


Property Wrappers

Aquí hay mucha magia detrás y estas propiedades son dignas de varios posts. Los property wrappers añaden una capa de separación entre el código que administra cómo se almacena una propiedad y el código que define una propiedad.

Por ejemplo, imagínate que queremos una propiedad que cada vez que se almacena un valor nuevo, el valor que se guarde también se haga una copia en la base de datos.
En lugar de escribir ese código en cada propiedad, puedes abstraer ese comportamiento una vez y reutilizar en todas las propiedades que quieras.

Para crear un property wrapper puedes usar un struct, enum o class. Vamos a ver un ejemplo con código:

@propertyWrapper
struct UserValidation {
    private var name: String
    
    init() { self.name = "" }
    
    var wrappedValue: String {
        get { name }
        set {
            if newValue.count > 5 {
                self.name = newValue
                print("Valid name")
            } else {
                print("Error")
            }
        }
    }
}

struct UserForm {
    @UserValidation var userName: String
}

var userForm = UserForm()
userForm.userName = "SwiftBeta"

userForm.userName

Lo que hemos hecho ha sido crear un property wrapper que hace una lógica específica cuando el nombre que se le asigna tiene más de 5 caracteres. En este caso se podría usar como parte de un validador de un formulario.

Los property wrappers son realmente muy potentes y los veremos en futuros posts.