es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Cómo cambiar el valor seleccionado de un DatePicker de SwiftUI programáticamente

Tengo un formulario en SwiftUI que consta de tres selecciones SwiftUI (dos DatePicker y uno Picker estándar). Estoy tratando de cambiar el valor seleccionado del segundo DatePicker cuando cambia el valor del Picker de cadena.

Estoy utilizando .onChange en el Picker de cadena para actualizar los valores subyacentes y esto funciona bien (agregué una fila de texto para mostrar el valor de la fecha de vencimiento para poder verificar el cambio). Sin embargo, me gustaría que el Picker de fecha de vencimiento actualice la fecha que muestra cuando cambia el valor vinculado.

*Los valores en la captura de pantalla a continuación son los valores establecidos inicialmente.

Imagen

struct FormWithPicker: View {
    @StateObject var formValues = FormValues()

    var body: some View {
        NavigationView {
            Form {
                // fecha de la factura
                DatePicker("Fecha de la factura:", selection: $formValues.invoiceDate, displayedComponents: [.date])

                // términos
                Picker("Términos:", selection: $formValues.invoiceTerms) {
                    ForEach(formValues.terms, id: \.self) { term in
                        Text(term)
                    }
                }
                .onChange(of: formValues.invoiceTerms, perform: { _ in
                    formValues.incrementDueDate()
                })

                // fecha de vencimiento
                DatePicker("Fecha de vencimiento:", selection: $formValues.dueDate, displayedComponents: [.date])

                // texto
                Text(formValues.dueDate.description)
            }
        }
    }
}
Tags:  ,

Answer

  1. Avatar for davy.ai

    Para actualizar el DatePicker de la Fecha de Vencimiento cuando el Selector de Términos cambie, puedes agregar otro modificador .onChange al Formulario con la vinculación $formValues.dueDate. En este modificador .onChange, puedes actualizar la fecha seleccionada del DatePicker a la nueva fecha de vencimiento calculada basada en el término seleccionado.

    Aquí tienes un fragmento de código actualizado con el modificador .onChange agregado:

    struct FormWithPicker: View {
        @StateObject var formValues = FormValues()
    
        var body: some View {
            NavigationView {
                Form {
                    // fecha de la factura
                    DatePicker("Fecha de la Factura:", selection: $formValues.invoiceDate, displayedComponents: [.date])
    
                    // términos
                    Picker("Términos:", selection: $formValues.invoiceTerms) {
                        ForEach(formValues.terms, id: \.self) { term in
                            Text(term)
                        }
                    }
                    .onChange(of: formValues.invoiceTerms) { newValue in
                        formValues.incrementDueDate()
                        // Actualizar la selección del DatePicker de la Fecha de Vencimiento
                        formValues.updateDueDateSelection()
                    }
    
                    // fecha de vencimiento
                    DatePicker("Fecha de Vencimiento:", selection: $formValues.dueDate, displayedComponents: [.date])
                        .onChange(of: formValues.dueDate) { newValue in
                            // Actualizar el valor de visualización de la fecha de vencimiento
                            formValues.updateDueDateText()
                        }
    
                    // texto
                    Text(formValues.dueDateDescription)
                }
            }
        }
    }
    

    En el modificador .onChange agregado para el Selector de Términos, llamamos al método formValues.updateDueDateSelection(), que actualiza el valor seleccionado del DatePicker de la Fecha de Vencimiento basado en el término seleccionado.

    Para implementar esta funcionalidad, puedes agregar los siguientes métodos a tu clase FormValues:

    class FormValues: ObservableObject {
        // ... propiedades y métodos existentes
    
        func incrementDueDate() {
            // Calcular la nueva fecha de vencimiento basada en el término seleccionado
            guard let termIndex = terms.firstIndex(of: invoiceTerms),
                  let termDays = termDays[termIndex] else { return }
            let newDueDate = Calendar.current.date(byAdding: .day, value: termDays, to: invoiceDate)
            dueDate = newDueDate ?? Date()
        }
    
        func updateDueDateSelection() {
            // Actualizar el valor seleccionado del DatePicker de la Fecha de Vencimiento
            let newSelection = Binding<date>(get: { self.dueDate },
                                              set: { self.dueDate = $0 })
            self.dueDateSelection = newSelection
        }
    
        func updateDueDateText() {
            // Actualizar el valor de visualización de la fecha de vencimiento
            let formatter = DateFormatter()
            formatter.dateStyle = .full
            formatter.timeStyle = .none
            dueDateDescription = formatter.string(from: dueDate)
        }
    }
    

    En el método incrementDueDate(), calculamos la nueva fecha de vencimiento basada en el término seleccionado y establecemos la propiedad dueDate con el nuevo valor.

    En el método updateDueDateSelection(), creamos un nuevo Binding para vincularlo al valor seleccionado del DatePicker de la Fecha de Vencimiento. Luego, establecemos la propiedad dueDateSelection con este nuevo Binding para actualizar la selección.

    En el método updateDueDateText(), actualizamos el valor formateado del string de la propiedad dueDateDescription basado en el nuevo valor de la fecha de vencimiento.

    Con estos métodos en su lugar, el DatePicker de la Fecha de Vencimiento debería actualizar su valor seleccionado cada vez que cambie el Selector de Términos.

Comments are closed.