Opcionales
## Objetivos de Aprendizaje
- Comprender que son los opcionales
- Usar tipos opcionales y desencapsulado
- Dominar enlace opcional
- Trabajar con fusion de nil
## Que son los Opcionales?
Los opcionales representan valores que pueden o no existir:
```swift
var nombre: String? = "Alicia"
var vacio: String? = nil
```
### Por Que Opcionales?
```swift
// Sin opcionales - no queda claro si el valor puede estar ausente
// String nombre = null; // Que significa null?
// Con opcionales - explicito sobre valores ausentes
let nombre: String? = nil
```
## Declaracion de Tipo Opcional
### Sintaxis
```swift
String? // Opcional String (puede contener String o nil)
Int? // Opcional Int
Double? // Opcional Double
Bool? // Opcional Bool
[String]? // Opcional Arreglo de Strings
```
### No Opcional vs Opcional
```swift
let cierto: String = "Hola" // Debe tener un valor
let talvez: String? = nil // Puede o no tener valor
```
## Desencapsulado Forzado
### Usando (!)
```swift
let nombre: String? = "Alicia"
print(nombre!) // "Alicia"
// ADVERTENCIA: Crashea si es nil!
let vacio: String? = nil
// print(vacio!) // CRASH EN TIEMPO DE EJECUCION!
```
### Cuando Evitar
```swift
// MAL - crashea si es nil
func obtenerNombreUsuario() -> String? { return nil }
let nombreUsuario = obtenerNombreUsuario()!
// print(nombreUsuario) // Crasheo!
```
## Enlace Opcional
### if let
```swift
let nombre: String? = "Alicia"
if let nombreDesencapsulado = nombre {
print("Hola, \(nombreDesencapsulado)")
} else {
print("No se proporciono nombre")
}
// Salida: Hola, Alicia
```
### guard let
```swift
func saludar(nombre: String?) {
guard let nombre = nombre else {
print("Sin nombre")
return
}
print("Hola, \(nombre)")
}
saludar(nombre: "Alicia") // Hola, Alicia
saludar(nombre: nil) // Sin nombre
```
### Enlace Multiple
```swift
let nombre: String? = "Alicia"
let edad: Int? = 30
if let nombreDesencapsulado = nombre, let edadDesencapsulada = edad {
print("\(nombreDesencapsulado) tiene \(edadDesencapsulada)")
}
// Puede combinar con condiciones
if let nombre = nombre, let edad = edad, edad >= 18 {
print("\(nombre) es adulto")
}
```
## Fusion de Nil
### Operador ??
```swift
let nombre: String? = nil
let nombreMostrar = nombre ?? "Anonimo"
print(nombreMostrar) // "Anonimo"
let nombreReal: String? = "Alicia"
let saludo = "Hola, \(nombreReal ?? "Invitado")"
print(saludo) // "Hola, Alicia"
```
### Encadenamiento
```swift
let anidado: String?? = nil
let resultado = anidado ?? "pordefecto" // "pordefecto"
let cadenaOpcional: String? = "Hola"
let resultado2 = cadenaOpcional ?? "nil o vacio" // "Hola"
```
## Opcionales Desencapsulados Implicitamente
### Declaracion
```swift
var opcionalImplicito: String! = "Hola"
print(opcionalImplicito) // No necesita desencapsular
```
### Casos de Uso
```swift
class ControladorVista {
var etiqueta: UILabel! // Se configurara despues
func viewDidLoad() {
etiqueta.text = "Hola" // Seguro porque sabemos que esta configurado
}
}
```
### Peligros
```swift
var peligroso: String! = nil
print(peligroso) // CRASHO!
```
## Encadenamiento Opcional
### Sintaxis de Encadenamiento Opcional
```swift
let calle: String? = direccion?.ciudad?.calle?.nombre
```
### Ejemplo
```swift
class Persona {
var residencia: Residencia?
}
class Residencia {
var direccion: Direccion?
}
class Direccion {
var calle: String = "123 Calle Principal"
}
let persona = Persona()
let calle = persona.residencia?.direccion?.calle
// calle es nil (residencia de persona es nil)
// Sin crasheo - el encadenamiento se corta
```
### Con Metodos
```swift
if let cantidad = persona.residencia?.calcularCantidadHabitaciones?() {
print("La casa tiene \(cantidad) habitaciones")
}
```
## Comparar Opcionales
### Igualdad
```swift
let a: Int? = 5
let b: Int? = 5
let c: Int? = nil
a == b // true
a == c // false
a == 5 // true (compara con no opcional)
c == nil // true
```
### Caso de Enum Opcional
```swift
enum Color {
case rojo, verde, azul
}
let seleccionado: Color? = .rojo
if seleccionado == .rojo {
print("Rojo esta seleccionado")
}
```
## Map y FlatMap
### Map Opcional
```swift
let numero: Int? = 5
let alCuadrado = numero.map { $0 * $0 } // Optional(25)
let numeroNil: Int? = nil
let nilAlCuadrado = numeroNil.map { $0 * $0 } // nil
```
### FlatMap Opcional
```swift
let cadena: String? = "42"
let entero = cadena.flatMap { Int($0) } // Optional(42)
let invalida: String? = "hola"
let noEntero = invalida.flatMap { Int($0) } // nil
```
## Coincidencia de Patrones
### switch con Opcionales
```swift
let valor: Int? = 5
switch valor {
case nil:
print("Es nil")
case let desencriptado?:
print("Tiene valor: \(desencriptado)")
}
```
### if case
```swift
let edad: Int? = 25
if case let desencriptado? = edad {
print("La edad es \(desencriptado)")
}
```
## Errores Comunes
### Nil Inesperado
```swift
func obtenerUsuario() -> String? { return nil }
let usuario = obtenerUsuario()
// usuario.uppercased() // ERROR: No se puede llamar en Opcional
// usuario!.uppercased() // CRASHO: valor nil
```
### Tipo Incorrecto
```swift
let cadena: String? = "123"
// let numero: Int = cadena // ERROR: No se puede asignar String? a Int
let numero: Int? = cadena.map { Int($0) }
```
## Mejores Practicas
### Hacer
```swift
// Usar enlace opcional
if let valor = opcional {
usar(valor)
}
// Usar guard para salida anticipada
func procesar() {
guard let valor = opcional else { return }
usar(valor)
}
// Usar fusion de nil para valores por defecto
let resultado = opcional ?? "pordefecto"
```
### No Hacer
```swift
// No forzar desencapsulado
// let valor = opcional! // PELIGROSO
// No comparar con nil explicitamente (preferir enlace opcional)
// if opcional != nil { } // No es idiomatico
```
## Resumen
- Los opcionales representan valores que pueden ser nil
- Declarar con sintaxis `Tipo?`
- Desencapsulado forzado con `!` (peligroso si es nil)
- Enlace opcional: `if let` y `guard let`
- Fusion de nil: `??` proporciona valor por defecto
- Encadenamiento opcional: `?.` accede propiedades de forma segura
- `map` y `flatMap` transforman valores opcionales
- Opcionales desencapsulados implicitamente (`Tipo!`) difieren el desencapsulado
- Preferir desencapsulado seguro sobre forzado
Comments
Comments powered by Giscus
To enable comments, add your Giscus embed code here.
Learn more about Giscus →