SwiftUI en 2026: estado, componentes y las nuevas APIs de iOS 18

SwiftUI lleva con nosotros desde 2019, cuando Apple lo presentó en la WWDC con iOS 13. En aquel momento era prometedor pero incompleto: faltaban componentes básicos, el sistema de navegación era rígido y muchas cosas acababan requiriendo un puente a UIKit. Seis años después, la situación ha cambiado bastante. Con iOS 18 y Xcode 16, SwiftUI es una opción sólida para construir aplicaciones completas sin tocar UIKit salvo casos muy específicos. Aquí repasamos el estado actual y las APIs más relevantes que llegaron con iOS 18.

El modelo de estado en 2026

El mayor cambio en SwiftUI de los últimos años no fue un componente nuevo sino una revisión del sistema de gestión de estado. Con iOS 17 llegó la macro @Observable, que sustituye a ObservableObject con una API más limpia y con mejor rendimiento:

import Observation

@Observable
class LibraryModel {
    var libros: [Libro] = []
    var filtroActivo: String = ""

    func cargar() async {
        libros = await BibliotecaService.fetchLibros()
    }
}

struct LibraryView: View {
    @State private var model = LibraryModel()

    var body: some View {
        List(model.libros.filter {
            model.filtroActivo.isEmpty || $0.titulo.contains(model.filtroActivo)
        }) { libro in
            Text(libro.titulo)
        }
        .task { await model.cargar() }
    }
}

A diferencia de @StateObject + ObservableObject, con @Observable solo se re-renderiza la vista cuando cambia una propiedad que esa vista concretamente está leyendo. El rendimiento mejora automáticamente sin trabajo extra.

Bindable para formularios

Para formularios con edición bidireccional, @Bindable permite crear bindings a modelos @Observable de forma directa:

struct EditarLibroView: View {
    @Bindable var libro: Libro

    var body: some View {
        Form {
            TextField("Título", text: $libro.titulo)
            TextField("Autor", text: $libro.autor)
        }
    }
}

Navegación con NavigationStack y rutas tipadas

El antiguo NavigationView quedó obsoleto hace tiempo. NavigationStack con rutas tipadas es la forma correcta de gestionar la navegación en 2026:

enum Ruta: Hashable {
    case detalle(Libro)
    case autor(String)
    case ajustes
}

struct AppRoot: View {
    @State private var ruta: [Ruta] = []

    var body: some View {
        NavigationStack(path: $ruta) {
            LibraryView(ruta: $ruta)
                .navigationDestination(for: Ruta.self) { destino in
                    switch destino {
                    case .detalle(let libro): DetalleLibroView(libro: libro)
                    case .autor(let nombre): AutorView(nombre: nombre)
                    case .ajustes: AjustesView()
                    }
                }
        }
    }
}

Con este patrón puedes navegar programáticamente desde cualquier parte del árbol, incluso desde un ViewModel, simplemente añadiendo o eliminando elementos del array ruta.

Novedades de iOS 18 en SwiftUI

Control Widget API

iOS 18 introduce los Controles, una nueva superficie de widgets que aparece en el Centro de Control y en la pantalla de bloqueo. Se crean con el nuevo tipo ControlWidget:

struct MiControl: ControlWidget {
    var body: some ControlWidgetConfiguration {
        StaticControlConfiguration(
            kind: "com.miapp.control.toggle"
        ) {
            ControlWidgetToggle(
                "Modo silencio",
                isOn: ModoSilencioIntent(),
                action: ToggleModoSilencioIntent()
            ) { activo in
                Image(systemName: activo ? "bell.slash" : "bell")
            }
        }
        .displayName("Modo silencio")
    }
}

ScrollView con efectos de desplazamiento

iOS 18 añade scrollTransition para aplicar efectos visuales a las vistas mientras se desplazan por un ScrollView:

ScrollView {
    LazyVStack {
        ForEach(items) { item in
            ItemView(item: item)
                .scrollTransition { view, phase in
                    view
                        .opacity(phase.isIdentity ? 1 : 0.3)
                        .scaleEffect(phase.isIdentity ? 1 : 0.8)
                }
        }
    }
}

Personalización del Tab Bar

Con iOS 18, TabView gana la capacidad de que el usuario reordene y oculte pestañas, similar al comportamiento nativo de Safari o la app de Música:

TabView {
    Tab("Inicio", systemImage: "house") {
        InicioView()
    }
    Tab("Buscar", systemImage: "magnifyingglass") {
        BusquedaView()
    }
    Tab("Perfil", systemImage: "person") {
        PerfilView()
    }
}
.tabViewCustomization($personalizacion)

Integración con Swift 6 y concurrencia

SwiftUI en iOS 18 está completamente alineado con el modelo de concurrencia de Swift 6. Los @MainActor se propagan automáticamente a las vistas y sus modelos @Observable. Si usas task {} o task(id:) {}, SwiftUI gestiona automáticamente la cancelación cuando la vista desaparece.

struct BuscadorView: View {
    @State private var resultados: [Resultado] = []
    @State private var query = ""

    var body: some View {
        List(resultados) { r in Text(r.titulo) }
            .searchable(text: $query)
            .task(id: query) {
                // Se cancela y relanza cada vez que query cambia
                guard !query.isEmpty else { resultados = []; return }
                resultados = await buscar(query)
            }
    }
}

Cuándo seguir usando UIKit

SwiftUI todavía tiene huecos. Las APIs de cámara personalizada, algunos gestos complejos, ciertos comportamientos de teclado y la integración profunda con MapKit siguen siendo más cómodos desde UIKit. Para esos casos, UIViewRepresentable y UIViewControllerRepresentable siguen siendo la solución limpia.

La tendencia es clara: Apple lleva años moviendo APIs nuevas directamente a SwiftUI sin equivalente UIKit, igual que ocurre en la plataforma Android con Jetpack Compose. La estrategia para proyectos nuevos es SwiftUI primero, y si algo no existe todavía en SwiftUI, un wrapper de UIKit. Para más contexto sobre desarrollo móvil multiplataforma, la serie de Kotlin Multiplatform en 2026 aborda el enfoque de código compartido entre iOS y Android.

Imagen: Pexels / ready made

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP