Programación en Swift y SwiftUI para iOS Developers

SwiftUI: Componente DatePicker

Para cualquier iOS Developer, la gestión de fechas y horas ha sido históricamente una fuente de dolores de cabeza. Desde el infierno de NSDateFormatter hasta la complejidad de los UIPickerView personalizados en UIKit. Sin embargo, la llegada de la programación Swift moderna y SwiftUI ha simplificado drásticamente este proceso.

Hoy vamos a diseccionar el componente DatePicker en SwiftUI. No solo aprenderemos a mostrarlo, sino a dominarlo, personalizarlo y adaptarlo a las particularidades de iOS, macOS y watchOS directamente desde Xcode.

¿Qué es DatePicker en SwiftUI?

El DatePicker es una estructura de vista nativa diseñada para seleccionar una fecha absoluta, una hora específica o ambas. Lo brillante de usar DatePicker en SwiftUI es su capacidad de adaptación: gestiona automáticamente la localización, los calendarios (Gregoriano, Japonés, etc.) y el formato de hora (12h/24h) basándose en la configuración del dispositivo del usuario.

La Anatomía Básica en Código

Para implementar un DatePicker, necesitas fundamentalmente una variable de estado (@State) de tipo Date que actúe como fuente de verdad.

struct BasicDatePickerView: View {
    @State private var selectedDate = Date()

    var body: some View {
        VStack {
            Text("Fecha seleccionada: \(selectedDate.formatted(date: .long, time: .shortened))")
                .padding()

            // El constructor más simple
            DatePicker("Seleccionar fecha", selection: $selectedDate)
                .padding()
        }
    }
}

Controlando el Tiempo: Rangos y Componentes

Un iOS Developer rara vez permite seleccionar *cualquier* fecha. Generalmente, hay reglas de negocio. SwiftUI nos permite restringir esto elegantemente.

1. Limitando el Rango (in: …)

Imagina una app de reservas donde no puedes reservar en el pasado, o una de cumpleaños donde no puedes nacer en el futuro.

<pre class="wp-block-syntaxhighlighter-code">struct BookingView: View {
    @State private var bookingDate = Date()
    
    // Rango: Desde ahora hasta el futuro infinito
    let dateRange: PartialRangeFrom<Date> = Date()...
    
    var body: some View {
        DatePicker(
            "Reserva tu mesa",
            selection: $bookingDate,
            in: dateRange, // Aquí aplicamos la restricción
            displayedComponents: [.date, .hourAndMinute]
        )
    }
}</pre>

2. Componentes Visuales

A veces solo necesitas la fecha (cumpleaños) o solo la hora (alarma). El parámetro displayedComponents es la clave.

  • .date: Muestra solo día, mes y año.
  • .hourAndMinute: Muestra solo horas y minutos.
  • Omítelo para mostrar ambos.

Estilizando el DatePicker: iOS vs macOS vs watchOS

Aquí es donde el DatePicker en SwiftUI brilla por su versatilidad. El modificador .datePickerStyle() cambia radicalmente la UX según la plataforma.

Estilos en iOS

En el iPhone, el espacio es premium. Tenemos tres opciones principales:

  • .compact (Por defecto): Muestra la fecha/hora en un botón que, al pulsarlo, despliega un calendario modal o un wheel.
  • .wheel: El clásico estilo “rodillo” de iOS antiguo. Útil para selectores de tiempo precisos (timers).
  • .graphical: Despliega el calendario completo directamente en la pantalla. Ideal para dashboards o selección de fechas en formularios grandes.
VStack {
    // Estilo Calendario Visual
    DatePicker("Calendario", selection: $date, displayedComponents: .date)
        .datePickerStyle(.graphical)
        .padding()
        .background(Color.blue.opacity(0.1), in: RoundedRectangle(cornerRadius: 10))
}

Estilos en macOS

En macOS, la interacción es vía ratón y teclado. El estilo .stepperField (exclusivo o por defecto en ciertos contextos de Mac) permite escribir la fecha o usar flechas.

Truco Pro: Si estás haciendo una app Catalyst o nativa de Mac, .graphical también funciona excelente para paneles laterales.

#if os(macOS)
DatePicker("Fecha", selection: $date)
    .datePickerStyle(.stepperField) // Específico de escritorio
#endif

Estilos en watchOS

El Apple Watch es el reto final de UX. Aquí no hay espacio para desperdiciar. Por defecto, watchOS apila los elementos. Usar .wheel en el reloj es muy común para temporizadores.

Tutorial Avanzado: El “Event Planner” Multiplataforma

Vamos a construir una vista completa que se adapte a las tres plataformas utilizando lo que hemos aprendido de programación Swift.

import SwiftUI

struct EventPlannerView: View {
    @State private var eventDate = Date()
    @State private var isAllDay = false
    
    // Validar que el evento sea en el futuro
    var isValidDate: Bool {
        eventDate >= Date()
    }
    
    var body: some View {
        NavigationStack {
            Form {
                Section(header: Text("Detalles del Evento")) {
                    Toggle("Todo el día", isOn: $isAllDay)
                    
                    // Lógica condicional para componentes
                    DatePicker(
                        "Comienza",
                        selection: $eventDate,
                        in: Date()..., // No permitir pasado
                        displayedComponents: isAllDay ? .date : [.date, .hourAndMinute]
                    )
                    // Adaptación de estilo inteligente
                    #if os(iOS)
                    .datePickerStyle(.compact)
                    #elseif os(macOS)
                    .datePickerStyle(.stepperField)
                    #endif
                }
                
                Section {
                    if isValidDate {
                        Text("Faltan \(Int(eventDate.timeIntervalSinceNow / 3600)) horas para el evento")
                            .foregroundStyle(.blue)
                    } else {
                        Text("La fecha no puede ser en el pasado")
                            .foregroundStyle(.red)
                    }
                }
                
                // Ejemplo de estilo gráfico para iOS/macOS
                #if !os(watchOS)
                Section(header: Text("Vista de Calendario")) {
                    DatePicker("Calendario", selection: $eventDate, displayedComponents: .date)
                        .datePickerStyle(.graphical)
                }
                #endif
            }
            .navigationTitle("Nuevo Evento")
        }
    }
}

#Preview {
    EventPlannerView()
}

Trucos de Experto en Xcode

1. Ocultar la Etiqueta (Label)

A menudo, el diseño UI requiere que el DatePicker esté centrado o sin texto a la izquierda. Puedes usar labelsHidden().

DatePicker("Título Oculto", selection: $date)
    .labelsHidden() // Solo muestra el control de fecha

2. Internacionalización Automática

No intentes forzar formatos dd/mm/yyyy manualmente dentro del picker. SwiftUI detecta la región del usuario. Si el usuario está en EEUU, verá mm/dd/yyyy. Si está en España, verá dd/mm/yyyy. Confía en el sistema.

3. UIDatePicker vs SwiftUI DatePicker

Aunque el DatePicker en SwiftUI es potente, si necesitas cambiar el color del texto del “wheel” en iOS, todavía es difícil hacerlo nativamente sin hacks. En esos casos extremos, un iOS Developer podría optar por envolver un UIDatePicker con UIViewRepresentable, pero para el 99% de los casos, la versión de SwiftUI es superior en rendimiento y facilidad de código.

Conclusión

El DatePicker en SwiftUI es un testimonio de cómo la programación Swift ha evolucionado para priorizar la funcionalidad declarativa sobre la implementación imperativa tediosa. Ya no necesitas calcular alturas de filas o gestionar delegados complejos.

Si tienes cualquier duda sobre este artículo, contacta conmigo y estaré encantado de ayudarte 🙂. Puedes contactar conmigo en mi perfil de X o en mi perfil de Instagram

Leave a Reply

Your email address will not be published. Required fields are marked *

Previous Article

Consejos para programar en SwiftUI

Next Article

Mejores patrones de diseño en SwiftUI

Related Posts