El control de flujo determina qué camino toma tu código según las condiciones del momento. En este post cubrimos if, switch, bucles y el poderoso guard — una herramienta de Swift moderno que cambia completamente cómo estructuras tus funciones.
if / else if / else
La estructura condicional básica. En Swift las condiciones no necesitan paréntesis (aunque puedes ponerlos), pero las llaves {} son obligatorias siempre.
let temperatura = 28
if temperatura > 35 {
print("Hace mucho calor")
} else if temperatura > 20 {
print("Temperatura agradable") // se imprime esto
} else {
print("Hace frío")
}
// En Swift 5.9+ puedes usar if como expresión para asignar un valor
let descripcion = if temperatura > 35 {
"Caluroso"
} else if temperatura > 20 {
"Agradable"
} else {
"Frío"
}
print(descripcion) // "Agradable"
switch — mucho más poderoso que en otros lenguajes
El switch de Swift es significativamente más potente que en lenguajes como Java o C. No necesita break, soporta rangos, tuplas y pattern matching avanzado. Cada case debe ser exhaustivo — si no cubres todos los casos, el compilador te lo exige.
// Switch básico — no necesita break
let diaSemana = 3
switch diaSemana {
case 1: print("Lunes")
case 2: print("Martes")
case 3: print("Miércoles") // se imprime esto
case 4: print("Jueves")
case 5: print("Viernes")
case 6, 7: print("Fin de semana") // múltiples valores en un case
default: print("Día inválido")
}
// Switch con rangos
let nota = 78
switch nota {
case 90...100: print("Sobresaliente")
case 70..<90: print("Notable") // se imprime esto
case 50..<70: print("Suficiente")
default: print("Insuficiente")
}
// Switch con where (condición adicional)
let valor = 15
switch valor {
case let x where x % 2 == 0:
print("\(x) es par")
case let x where x % 2 != 0:
print("\(x) es impar") // se imprime esto
default:
break
}
Bucle for-in
El bucle más usado en Swift. Itera sobre colecciones, rangos y secuencias. Es limpio, seguro y expresivo.
// Iterar un rango
for i in 1...5 {
print(i)
}
// Iterar un array
let idiomas = ["Swift", "Kotlin", "Python"]
for idioma in idiomas {
print(idioma)
}
// Ignorar el índice con _
for _ in 1...3 {
print("Repetición")
}
// Iterar con índice usando enumerated()
for (indice, idioma) in idiomas.enumerated() {
print("\(indice + 1). \(idioma)")
}
// Iterar un diccionario
let capitales = ["México": "CDMX", "España": "Madrid", "Argentina": "Buenos Aires"]
for (pais, capital) in capitales {
print("\(pais) → \(capital)")
}
Bucles while y repeat-while
Se usan cuando no sabes de antemano cuántas iteraciones necesitas. while evalúa la condición antes de ejecutar, repeat-while la evalúa después (garantiza al menos una ejecución).
// while — evalúa primero
var contador = 0
while contador < 5 {
print(contador)
contador += 1
}
// repeat-while — ejecuta al menos una vez
var intento = 0
repeat {
print("Intento \(intento)")
intento += 1
} while intento < 3
break y continue
break detiene el bucle por completo. continue salta a la siguiente iteración sin ejecutar el resto del código del ciclo actual.
// break — detiene el bucle
for numero in 1...10 {
if numero == 6 { break }
print(numero) // imprime 1, 2, 3, 4, 5
}
// continue — salta esa iteración
for numero in 1...10 {
if numero % 2 == 0 { continue }
print(numero) // imprime solo los impares: 1, 3, 5, 7, 9
}
guard — la joya de Swift moderno
guard es uno de los elementos más importantes de Swift y está ausente en la mayoría de otros lenguajes. Su función es validar condiciones al inicio de una función y salir inmediatamente si no se cumplen. Esto elimina el anidamiento excesivo de if y hace el código mucho más legible.
// Sin guard — el "pyramide de la muerte"
func procesarSinGuard(nombre: String?, edad: Int?) {
if let nombre = nombre {
if let edad = edad {
if edad >= 18 {
print("Procesando: \(nombre), \(edad) años")
} else {
print("Menor de edad")
}
} else {
print("Edad inválida")
}
} else {
print("Nombre inválido")
}
}
// Con guard — lineal, fácil de leer
func procesarConGuard(nombre: String?, edad: Int?) {
guard let nombre = nombre else {
print("Nombre inválido")
return
}
guard let edad = edad else {
print("Edad inválida")
return
}
guard edad >= 18 else {
print("Menor de edad")
return
}
// Aquí sabemos que nombre y edad son válidos
print("Procesando: \(nombre), \(edad) años")
}
procesarConGuard(nombre: "Usuario", edad: 25) // "Procesando: Usuario, 25 años"
procesarConGuard(nombre: nil, edad: 25) // "Nombre inválido"
procesarConGuard(nombre: "Usuario", edad: 15) // "Menor de edad"
La regla es simple: usa guard para los casos de error o condiciones que deben cumplirse para que el código tenga sentido. Todo lo que venga después del guard ya está validado — el camino feliz queda limpio y plano.
Resumen
- if/else: condiciones simples; en Swift 5.9+ también puede usarse como expresión para asignar valores.
- switch: exhaustivo, sin break, soporta rangos y pattern matching con where.
- for-in: el bucle principal de Swift, itera sobre cualquier secuencia.
- while / repeat-while: cuando el número de iteraciones es desconocido.
- guard: valida condiciones al inicio y sale si no se cumplen — elimina el anidamiento y mejora la legibilidad.
En el siguiente post llegamos a uno de los temas más importantes y característicos de Swift: los Opcionales.