Las propiedades estáticas y de clase son propiedades que pertenecen al tipo en lugar de a la instancia. Históricamente, surgieron para resolver el problema de almacenar información común para todas las instancias (por ejemplo, contadores, configuraciones, fábricas). En Swift, se puede usar static en todos los tipos (class, struct, enum), y class solo en clases y solo para propiedades calculadas, permitiendo su sobrescritura en los herederos.
Problema: El uso incorrecto de las propiedades estáticas puede llevar a condiciones de carrera y errores al acceder desde diferentes hilos. También es fácil confundir static y class y elegir incorrectamente el mecanismo para sobrescribir en los herederos.
Solución:
Ejemplo de código:
class Counter { static var count = 0 static let queue = DispatchQueue(label: "counter.queue") static func increment() { queue.sync { count += 1 } } class var typeDescription: String { return "Contador Genérico" } } class NamedCounter: Counter { override class var typeDescription: String { return "Contador Nombrado" } }
Características clave:
Pregunta 1: ¿Se puede declarar una propiedad static let como una propiedad calculada (computed)?
Sí, una propiedad estática puede ser tanto almacenada como calculada. Para las propiedades let, generalmente es una constante, sin embargo, static var puede ser perfectamente calculada:
struct Math { static var pi: Double { return 3.1415926 } }
Pregunta 2: ¿Son thread-safe las static var por defecto?
No, si static var se modifica desde diferentes hilos, pueden ocurrir condiciones de carrera. read/write debe ser sincronizado manualmente.
Pregunta 3: ¿Se puede usar class var para propiedades almacenadas?
No, class var siempre debe ser una propiedad calculada (property with get/optional set), las propiedades almacenadas solo están permitidas para static.
En la aplicación, el contador de acceso del usuario se almacenaba en static var y se incrementaba desde diferentes hilos sin sincronización.
Ventajas:
Desventajas:
Para un objeto de configuración global, se utilizó static let y el acceso a él era solo de lectura o mediante el uso de DispatchQueue para la escritura.
Ventajas:
Desventajas: