Bienvenido. Si estás leyendo esto, es porque has decidido dar el paso. Quieres crear aplicaciones para iPhone, Mac, iPad o incluso visionOS. Has llegado en el momento perfecto. SwiftUI ya no es “el futuro”; es el presente absoluto.
Este artículo no es solo un tutorial; es un mapa de ruta. Vamos a ignorar la jerga innecesaria y nos centraremos en cómo pensar como un desarrollador de Apple. Prepárate un café, abre tu mente y vamos a empezar.
Módulo 1: La Filosofía y el Entorno
¿Qué es SwiftUI y por qué debería importarme?
Antes de escribir código, debes entender el cambio de paradigma. Antiguamente (hace unos 6 años), programábamos de forma Imperativa. Le decíamos al ordenador cómo hacer las cosas paso a paso:
- Crea un botón.
- Ponlo en la posición X: 50, Y: 100.
- Cambia su color a rojo.
- Si alguien lo toca, cambia el texto.
SwiftUI es Declarativo. Tú le dices al ordenador qué quieres, y él se encarga del cómo.
- “Quiero una lista de tareas que muestre este array de datos”.
- “Quiero que el texto sea rojo cuando haya un error”.
Tú defines las reglas, SwiftUI dibuja la interfaz. Si los datos cambian, SwiftUI redibuja la interfaz automáticamente por ti.
Tu Herramienta: Xcode
Para programar necesitas un taller. Ese taller es Xcode.
- Descárgalo gratis desde la Mac App Store.
- Al abrirlo, verás la opción “Create New Project”.
- Selecciona App (bajo la pestaña iOS).
- Nombre del proyecto:
HolaSwiftUI. - Interface: SwiftUI (obvio).
- Language: Swift.
Al abrirse, verás tres áreas principales:
- Izquierda: El Navegador (tus archivos).
- Centro: El Editor (tu código) y el Canvas (la previsualización visual en tiempo real).
- Derecha: El Inspector (propiedades).
Módulo 2: Los Fundamentos de Swift (Crash Course)
SwiftUI está escrito en Swift. No necesitas ser un experto en Swift para empezar, pero necesitas conocer los ladrillos básicos.
Variables y Constantes
var: Algo que puede cambiar (Variable).let: Algo que nunca cambia (Constante). Úsalo siempre que puedas por seguridad.
var nombre = "Juan"
nombre = "Pedro" // ✅ Válido
let fechaNacimiento = "1990"
// fechaNacimiento = "2000" // ❌ Error: No puedes cambiar una constanteStructs (Estructuras)
SwiftUI se basa casi enteramente en structs. Imagina una estructura como un plano para crear algo.
struct Perro {
var nombre: String
var raza: String
}
let miPerro = Perro(nombre: "Firulais", raza: "Labrador")En SwiftUI, todas tus pantallas (Vistas) son structs. Son ligeras, rápidas y seguras.
Módulo 3: Tu Primera Vista en SwiftUI
Mira el archivo ContentView.swift. Verás algo así:
import SwiftUI
struct ContentView: View {
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(.tint)
Text("Hello, world!")
}
.padding()
}
}Vamos a diseccionar esto línea por línea. Es crucial.
struct ContentView: View: Estás creando una estructura llamadaContentViewque se comporta como unaView(Vista). El protocoloViewes el contrato: promete que esta estructura sabrá dibujarse en pantalla.var body: some View: Esta es la única propiedad obligatoria. SwiftUI te pregunta: “¿Cuál es el cuerpo de esta vista?”. Tú debes devolver algo que sea una vista.Text("Hello, world!"): Esto es un componente básico. Muestra texto.
Modificadores: El “Pincel” de SwiftUI
¿Ves el .padding() o .foregroundStyle(.tint)? Se llaman Modificadores. Toman una vista (como el Texto), le aplican un cambio, y devuelven una nueva vista modificada.
Text("Hola, SwiftUI")
.font(.largeTitle) // Hace la letra grande
.fontWeight(.bold) // La hace negrita
.foregroundColor(.blue) // La pinta de azul
.padding() // Añade aire alrededor
.background(Color.yellow) // Pone fondo amarillo⚠️ El orden importa: Imagina que eres un pintor.
- Si pintas el fondo amarillo y luego añades margen (padding), el margen será transparente.
- Si añades margen y luego pintas el fondo, el margen también será amarillo.
Módulo 4: El Sistema de Diseño (Stacks)
En el diseño clásico, usábamos coordenadas (X, Y). En SwiftUI, usamos Cajas. Hay tres tipos principales de cajas para organizar elementos:
- VStack (Vertical Stack): Apila elementos uno debajo de otro.
- HStack (Horizontal Stack): Pone elementos uno al lado del otro.
- ZStack (Depth Stack): Pone elementos uno encima del otro (hacia el fondo, como capas de Photoshop).
Ejemplo Práctico: Tarjeta de Perfil
Vamos a crear una tarjeta de usuario sencilla.
struct ProfileCard: View {
var body: some View {
HStack { // Caja Horizontal
Image(systemName: "person.circle.fill") // Icono
.font(.system(size: 60))
.foregroundColor(.blue)
VStack(alignment: .leading) { // Caja Vertical (alineada a la izquierda)
Text("Gemini AI")
.font(.headline)
Text("Desarrollador iOS")
.font(.subheadline)
.foregroundColor(.gray)
}
}
.padding() // Margen interno
.background(Color.white) // Fondo blanco
.cornerRadius(10) // Bordes redondeados
.shadow(radius: 5) // Sombra
}
}Copia y pega esto en tu Xcode. Verás cómo las pilas (Stacks) crean estructura sin necesidad de matemáticas complejas.
Spacers (Espaciadores)
El Spacer() es un muelle invisible. Ocupa todo el espacio posible, empujando a los demás elementos.
HStack { Text("A") Spacer() Text("B") }: “A” a la izquierda, “B” a la derecha, espacio vacío en medio.
Módulo 5: State Management (El corazón de la app)
Aquí es donde los principiantes suelen atascarse. Lee con atención. Una app no es estática; cambia. El usuario toca botones, escribe texto, descarga datos. En SwiftUI, la Vista es una función de su Estado.
UI = f(State)
Si el estado cambia, la UI se redibuja automáticamente. Para decirle a SwiftUI que una variable es “especial” y debe vigilarla, usamos Property Wrappers.
@State (Estado Local)
Usa @State para variables simples que pertenecen solo a esa vista (como si un botón está pulsado o qué texto hay en un campo).
struct CounterView: View {
// 1. Declaramos el estado.
// SwiftUI ahora "observa" esta variable.
@State private var count = 0
var body: some View {
VStack {
Text("Has pulsado: \(count) veces")
.font(.title)
Button("Púlsame") {
// 2. Cambiamos el estado.
// Automáticamente, SwiftUI destruye la vista y la vuelve a crear con el nuevo valor.
count += 1
}
.buttonStyle(.borderedProminent)
}
}
}@Binding (Conexión)
¿Qué pasa si tienes una vista “Padre” y una vista “Hijo”, y quieres que el hijo cambie un dato del padre? No puedes pasar la variable normal, porque en Swift las estructuras se pasan por copia (valor). Necesitas un “enlace” o referencia.
- Padre: Tiene el
@State. - Hijo: Tiene el
@Binding.
struct InterruptorView: View {
@State private var encendido = false // La verdad absoluta vive aquí
var body: some View {
VStack {
// Pasamos la variable con '$' para crear el enlace
BotonInterruptor(estaEncendido: $encendido)
if encendido {
Text("¡Luz encendida!")
}
}
}
}
struct BotonInterruptor: View {
// Binding no tiene valor propio, apunta al @State del padre
@Binding var estaEncendido: Bool
var body: some View {
Button(estaEncendido ? "Apagar" : "Encender") {
estaEncendido.toggle() // Esto cambia la variable en el PADRE
}
}
}Módulo 6: Listas y Datos Dinámicos
Las apps reales muestran listas de cosas. En UIKit usábamos UITableView (que era doloroso). En SwiftUI usamos List.
Para mostrar datos en una lista, los datos deben ser Identifiable (deben tener un ID único).
// 1. Definimos el modelo de datos
struct Tarea: Identifiable {
let id = UUID() // Genera un ID único automáticamente
let nombre: String
}
struct ListaTareasView: View {
// 2. Nuestros datos
let tareas = [
Tarea(nombre: "Aprender Swift"),
Tarea(nombre: "Hacer ejercicio"),
Tarea(nombre: "Leer 5000 palabras")
]
var body: some View {
// 3. La Lista
List(tareas) { tarea in
// Cómo se ve CADA fila
HStack {
Image(systemName: "circle")
Text(tarea.nombre)
}
}
}
}sí de simple. SwiftUI recorre el array y crea una fila por cada elemento.
Módulo 7: Navegación
¿Cómo pasamos de una pantalla a otra? Usamos NavigationStack y NavigationLink.
Piénsalo como una baraja de cartas.
NavigationStack: Es la mesa donde pones las cartas. Envuelve a tu vista principal.NavigationLink: Es la acción de poner una carta nueva encima.
struct MenuView: View {
var body: some View {
NavigationStack {
List {
NavigationLink("Ver Perfil") {
// Destino
ProfileCard()
}
NavigationLink("Ver Ajustes") {
Text("Pantalla de Ajustes")
}
}
.navigationTitle("Menú Principal")
}
}
}Módulo 8: Tutorial Práctico – “ColorMinder”
Vamos a unir todo lo aprendido para crear una mini-app. Idea: Una app que te deja guardar una lista de colores favoritos y ver sus detalles.
Paso 1: El Modelo
Crea un archivo ColorItem.swift.
import SwiftUI
struct ColorItem: Identifiable {
let id = UUID()
let name: String
let color: Color
let description: String
}Paso 2: La Vista de Detalle
Crea ColorDetailView.swift. Esta vista recibirá un color y lo mostrará en grande.
import SwiftUI
struct ColorDetailView: View {
let item: ColorItem // Recibe datos, no necesita estado
var body: some View {
ZStack {
item.color.ignoresSafeArea() // Fondo de pantalla completo
VStack {
Text(item.name)
.font(.system(size: 50, weight: .bold))
.foregroundStyle(.white)
Text(item.description)
.font(.title2)
.foregroundStyle(.white.opacity(0.8))
.padding()
}
}
}
}Paso 3: La Lista Principal (ViewModel + Vista)
En aplicaciones modernas, usamos el framework Observation para separar la lógica. Crea ColorViewModel.swift.
import Foundation
import SwiftUI
import Observation
@Observable
class ColorViewModel {
var items: [ColorItem] = [
ColorItem(name: "Azul Océano", color: .blue, description: "Calmante y profundo."),
ColorItem(name: "Rojo Fuego", color: .red, description: "Pasión y energía."),
ColorItem(name: "Verde Bosque", color: .green, description: "Naturaleza y vida."),
ColorItem(name: "Amarillo Sol", color: .yellow, description: "Alegría y luz.")
]
func addItem() {
// Simulación de añadir uno random
items.append(ColorItem(name: "Nuevo Morado", color: .purple, description: "Misterioso."))
}
}Y finalmente, tu ContentView.swift:
struct ContentView: View {
// Instanciamos el ViewModel
@State private var viewModel = ColorViewModel()
var body: some View {
NavigationStack {
List(viewModel.items) { item in
NavigationLink(destination: ColorDetailView(item: item)) {
HStack {
Circle()
.fill(item.color)
.frame(width: 30, height: 30)
Text(item.name)
.font(.headline)
}
}
}
.navigationTitle("Mis Colores")
.toolbar {
Button("Añadir", systemImage: "plus") {
viewModel.addItem()
}
}
}
}
}Módulo 9: Arquitectura y Mejores Prácticas (Nivel Intermedio)
Ahora que sabes crear la app, hablemos de cómo no crear un desastre de código (“Spaghetti Code”).
MVVM (Model – View – ViewModel)
Es el patrón que acabamos de usar en “ColorMinder”.
- Model: Tus datos puros (
struct ColorItem). No sabe nada de la pantalla. - View: Tu pantalla (
ContentView). Solo sabe pintar. No debe tener lógica compleja (como llamadas a internet). - ViewModel: El cerebro (
class ColorViewModel). Tiene los datos, hace las llamadas a la base de datos o API, y le dice a la vista “¡Oye, he cambiado, redibújate!”.
Separación de Vistas
Un error común de principiante es meter todo el código en un solo archivo. Si tu body tiene más de 50 líneas, es hora de extraer sub-vistas.
Mal:
var body: some View {
VStack {
// 50 líneas de código para una tarjeta
// 50 líneas de código para un botón
}
}Bien:
var body: some View {
VStack {
TarjetaView()
BotonPersonalizadoView()
}
}Selecciona el código en Xcode, haz clic derecho -> “Refactor” -> “Extract Subview”. Xcode lo hace por ti.
Módulo 10: Recursos y Siguientes Pasos
Has llegado al final de este tutorial masivo. Ahora tienes los fundamentos: Variables, Vistas, Stacks, Modificadores, Estado, Listas y Navegación.
¿Qué sigue?
- Swift Data: Para guardar datos permanentemente en el dispositivo (base de datos).
- API Networking: Usar
URLSessionpara descargar datos de internet (JSON). - Animaciones: SwiftUI tiene el sistema de animación más fácil del mundo. Prueba a añadir
.animation(.default, value: variable)a una vista.
Errores Comunes a Evitar
- Pelear con el sistema: Si algo parece increíblemente difícil en SwiftUI (como cambiar el color de un pixel específico manualmente), probablemente lo estás haciendo mal. Busca la “manera SwiftUI”.
- Mezclar lógica y UI: Mantén tus cálculos fuera del
body. - Ignorar los Previews: Usa el Canvas. Te ahorra horas de compilar y ejecutar el simulador.
Despedida
Aprender a programar es una maratón, no un sprint. Habrá días en los que el código no compile y quieras tirar el Mac por la ventana. Es normal. Respira, lee el error (Xcode suele decirte qué pasa).









