Las clases (class) y las estructuras (struct) son plantillas que te permiten modelar datos del mundo real dentro de tu app iOS.
Con ellas puedes representar cosas como un producto de Mercado Libre, un usuario de Liverpool o un pedido de Bimbo. Ambas agrupan propiedades y métodos en un solo lugar.
Diferencias fundamentales entre class y struct
Antes de escribir código, necesitas entender una diferencia clave: el comportamiento al copiarse.
- Una
structes un tipo por valor. Cuando la asignas a otra variable, Swift crea una copia independiente. - Una
classes un tipo por referencia. Cuando la asignas a otra variable, ambas variables apuntan al mismo objeto en memoria.
Esta diferencia cambia cómo se comporta tu app. Elegir mal puede causar errores difíciles de detectar.
Sintaxis de una struct
La estructura básica de una struct es:
struct NombreDelTipo {
var propiedad1: Tipo
var propiedad2: Tipo
func nombreDelMetodo() -> Tipo {
// lógica
}
}
Todos los nombres de tipos —tanto struct como class— se escriben en UpperCamelCase: la primera letra de cada palabra en mayúscula.
Ejemplo 1: struct para un producto de Mercado Libre
Imagina que tu app muestra productos. Crea una struct llamada Producto:
struct Producto {
var nombre: String
var precio: Double
var disponible: Bool
func descripcion() -> String {
let estado = disponible ? "En stock" : "Agotado"
return "\(nombre) — $\(precio) — \(estado)"
}
}
Ahora crea una instancia (un objeto concreto basado en la plantilla):
var tenis = Producto(nombre: "Tenis Running", precio: 1200, disponible: true)
print(tenis.descripcion())
// Salida: Tenis Running — $1,200 — En stock
Fíjate en el inicializador automático: Swift genera init gratis para las struct. Solo pasas los valores en el orden de las propiedades.
Sintaxis de una class
class NombreDelTipo {
var propiedad1: Tipo
var propiedad2: Tipo
init(propiedad1: Tipo, propiedad2: Tipo) {
self.propiedad1 = propiedad1
self.propiedad2 = propiedad2
}
func nombreDelMetodo() {
// lógica
}
}
A diferencia de struct, una class no genera init automático. Debes escribirlo tú mismo. Usa self. para distinguir entre la propiedad del objeto y el parámetro del init.
Ejemplo 2: class para un usuario de Liverpool
Cuando varios módulos de tu app necesitan compartir y modificar el mismo objeto, usa class:
class Usuario {
var nombre: String
var saldo: Double
init(nombre: String, saldo: Double) {
self.nombre = nombre
self.saldo = saldo
}
func agregarSaldo(_ cantidad: Double) {
saldo += cantidad
print("Nuevo saldo de \(nombre): $\(saldo)")
}
}
Crea una instancia y modifícala:
let clienta = Usuario(nombre: "Sofía", saldo: 5000)
clienta.agregarSaldo(2500)
// Salida: Nuevo saldo de Sofía: $7,500
Nota importante: aunque clienta es constante (let), puedes modificar sus propiedades porque es una referencia. Con struct, esto no funciona así.
Tipo por valor vs. tipo por referencia en la práctica
Este bloque de código muestra la diferencia de forma directa:
// Con struct (tipo por valor)
var pedidoA = Producto(nombre: "Leche Bimbo", precio: 35, disponible: true)
var pedidoB = pedidoA // Se crea una COPIA
pedidoB.precio = 40
print(pedidoA.precio) // 35 — no cambió
print(pedidoB.precio) // 40
// Con class (tipo por referencia)
let usuarioX = Usuario(nombre: "Carlos", saldo: 3000)
let usuarioY = usuarioX // Apuntan al MISMO objeto
usuarioY.agregarSaldo(1500)
print(usuarioX.saldo) // 4,500 — sí cambió
Esta es la razón principal por la que Swift prefiere struct para datos simples y class para objetos compartidos en la app.
Propiedades calculadas
Tanto struct como class soportan propiedades calculadas: valores que se derivan de otras propiedades, sin almacenarse por separado.
struct Pedido {
var subtotal: Double
var descuento: Double
var total: Double {
return subtotal - descuento
}
}
let pedidoFEMSA = Pedido(subtotal: 8500, descuento: 500)
print(pedidoFEMSA.total)
// Salida: 8000.0
La propiedad total no ocupa espacio en memoria extra; se calcula cada vez que la lees.
Cuándo usar struct y cuándo usar class
| Situación | Usa |
|---|---|
| Modelar datos simples (producto, dirección, precio) | struct |
| Compartir estado entre varias partes de la app | class |
| Necesitas herencia (un tipo que extiende otro) | class |
| Trabajas con SwiftUI (la mayoría de los casos) | struct |
Integras con frameworks de Apple como UIViewController |
class |
| El objeto tiene un ciclo de vida claro (abrir/cerrar sesión) | class |
En SwiftUI, casi todo el código de la interfaz usa struct. En UIKit, las vistas y controladores son class.
Ejemplo 3: Combinando struct y class en una app de FEMSA
Una app real mezcla ambos. Los datos son struct; el controlador que los gestiona es class:
struct Sucursal {
var nombre: String
var ciudad: String
var ventasDiarias: Double
}
class GestorDeSucursales {
var sucursales: [Sucursal] = []
func agregar(_ sucursal: Sucursal) {
sucursales.append(sucursal)
}
func totalVentas() -> Double {
return sucursales.reduce(0) { $0 + $1.ventasDiarias }
}
}
let gestor = GestorDeSucursales()
gestor.agregar(Sucursal(nombre: "OXXO Reforma", ciudad: "CDMX", ventasDiarias: 18500))
gestor.agregar(Sucursal(nombre: "OXXO Monterrey", ciudad: "MTY", ventasDiarias: 14200))
print(gestor.totalVentas())
// Salida: 32700.0
Esta separación mantiene el código limpio y fácil de mantener.
Errores comunes
1. Olvidar el init en una class
Si declaras una class con propiedades sin valores por defecto y no escribes init, el compilador marca error. La solución es siempre definir init o asignar valores por defecto.
// ❌ Error
class Empleado {
var nombre: String // No tiene valor por defecto ni init
}
// ✅ Correcto
class Empleado {
var nombre: String
init(nombre: String) { self.nombre = nombre }
}
2. Modificar una struct en una constante
Si declaras una instancia de struct con let, sus propiedades son inmutables aunque estén declaradas con var dentro de la struct.
let producto = Producto(nombre: "Pan Bimbo", precio: 28, disponible: true)
producto.precio = 30 // ❌ Error: no puedes mutar una struct constante
var productoCambiable = Producto(nombre: "Pan Bimbo", precio: 28, disponible: true)
productoCambiable.precio = 30 // ✅ Correcto
3. Confundir referencia compartida con copia
Este error genera bugs silenciosos. Cuando asignas una class a otra variable, no obtienes una copia. Si necesitas una copia real, debes implementar un método clone() o usar struct.
Resumen de sintaxis
| Característica | struct |
class |
|---|---|---|
| Tipo | Por valor | Por referencia |
init automático |
✅ Sí | ❌ No |
| Herencia | ❌ No | ✅ Sí |
mutating para métodos que modifican propiedades |
Necesario | No necesario |
| Uso en SwiftUI | Principal | Secundario |
Puntos clave
- Usa
structpara datos simples e independientes; usaclasscuando varios módulos deban compartir el mismo objeto. - Las
structson tipo por valor: cada asignación crea una copia. Lasclassson tipo por referencia: todas las variables apuntan al mismo objeto. - Las
structgeneraninitautomáticamente. Lasclassrequieren que lo escribas conself.. - Las propiedades calculadas derivan su valor de otras propiedades y funcionan en ambos tipos.
- En SwiftUI, la mayoría del código de interfaz usa
struct. En UIKit, los controladores usanclass.