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.

Comportamiento extraño de wrappedValue en @State de SwiftUI

Para ir al grano, tengo este código:

struct DataModel { var option: String }

struct ViewModel { var selected: String? = "1" var options = [DataModel(option: "1"), DataModel(option: "2"), DataModel(option: "3")] }

struct ContentView: View { @State var viewModel: ViewModel

var body: some View { VStack { Picker("test", selection: aBinder()) { ForEach(viewModel.options, id: \.option) { option in Text(option.option) } } .background(Color.red) } }

func aBinder() -> Binding<string?> { Binding<string?> { viewModel.selected } set: { value in $viewModel.selected.wrappedValue = value print($viewModel.selected.wrappedValue) } } }

El valor de “selected” en el ViewModel no cambia.

Esto funciona:

struct DataModel { var option: String }

struct ViewModel { var selected: String = "1" var options = [DataModel(option: "1"), DataModel(option: "2"), DataModel(option: "3")] }

struct ContentView: View { @State var viewModel: ViewModel

var body: some View { VStack { Picker("test", selection: $viewModel.selected) { ForEach(viewModel.options, id: \.option) { option in Text(option.option) } } Button("press me", action: { print(viewModel.selected) }) } } }

Pero eso no tiene ningún sentido. En ambos casos uso una vinculación para almacenar el valor actual. ¿Qué está pasando? Soy bastante nuevo en swiftUI, así que puede que me haya perdido cómo funciona algo.

Gracias de antemano.</string?></string?>

Tags:  , ,

Answer

  1. Avatar for davy.ai

    El problema es con el tipo de variable selected en la estructura ViewModel. En el primer fragmento de código, se declara como una cadena opcional (String?). Sin embargo, en el segundo fragmento de código, se declara como una cadena no opcional (String).

    Cuando se utiliza una vista Picker con una vinculación, el tipo de la variable vinculada debe coincidir con el tipo de la opción DataModel. Dado que la propiedad option en DataModel es una cadena no opcional, la variable selected en ViewModel también debería ser una cadena no opcional.

    En el primer fragmento de código, cuando se establece la variable selected dentro del cierre de vinculación, no se desempaqueta y el valor opcional se asigna a viewModel.selected.wrappedValue. Esto no actualiza la variable selected en la estructura ViewModel.

    Para solucionarlo, puede cambiar el tipo de selected a una cadena no opcional y actualizar el cierre de vinculación para asignar el valor desempaquetado a viewModel.selected, o puede agregar un desempaquetado explícito del valor opcional en el cierre de vinculación de la siguiente manera:

    func aBinder() -> Binding<string?> {
        Binding<string?> {
            viewModel.selected
        } set: { value in
            if let value = value {
                viewModel.selected = value
                print(viewModel.selected)
            }
        }
    }
    

    La declaración if let verifica si el valor opcional no es nulo y lo desempaqueta antes de asignarlo a viewModel.selected. Esto actualizará la variable selected en la estructura ViewModel.</string?></string?>

Comments are closed.