Gibt es eine Möglichkeit, eine Funktion aufzurufen, wenn sich eine SwiftUI Picker-Auswahl ändert?

8

Ich möchte eine Funktion aufrufen, wenn sich der Wert von selectedOption ändert. Gibt es eine Möglichkeit, dies in SwiftUI ähnlich wie beim Bearbeiten eines TextFields zu tun?

Insbesondere möchte ich die ausgewählte Option speichern, wenn der Benutzer die ausgewählte Option ändert.

Hier ist meine Auswahl:

struct BuilderPicker: View {
    let name: String
    let options: Array<String>
    @State var selectedOption = 0
    var body: some View {
        HStack {
            Text(name)
                .font(.body)
                .padding(.leading, 10)
            Picker(selection: $selectedOption, label: Text(name)) {
                ForEach(0 ..< options.count) {
                    Text(self.options[$0]).tag($0)
                }
            }.pickerStyle(SegmentedPickerStyle())
                .padding(.trailing, 25)
        }.onTapGesture {
            self.selectedOption = self.selectedOption == 0 ? 1 : 0
        }
            .padding(.init(top: 10, leading: 10, bottom: 10, trailing: 0))
            .border(Color.secondary, width: 3)
            .padding(.init(top: 0, leading: 15, bottom: 0, trailing: 15))
            .font(.body)
    }

}

Ich bin noch neu bei SwiftUI und würde gerne Hilfe bekommen. Vielen Dank!

Eli Front
quelle

Antworten:

10

Wenn der @ State-Wert in einer Ansicht verwendet wird, benötigen Sie keine zusätzliche Variable name

  struct BuilderPicker: View {
// let name: String = ""
 let options: Array<String> = ["1", "2","3","4","5"]
 @State var selectedOption = 0
 var body: some View {
    HStack {
        Text(options[selectedOption])
            .font(.body)
            .padding(.leading, 10)
        Picker(selection: $selectedOption, label:    Text(options[selectedOption])) {
            ForEach(0 ..< options.count) {
                Text(self.options[$0]).tag($0)
            }
        }.pickerStyle(SegmentedPickerStyle())
            .padding(.trailing, 25)}
//        }.onTapGesture {
//            self.selectedOption = self.selectedOption == 0 ? 1 : 0
//        }
        .padding(.init(top: 10, leading: 10, bottom: 10, trailing: 0))
        .border(Color.secondary, width: 3)
        .padding(.init(top: 0, leading: 15, bottom: 0, trailing: 15))
        .font(.body)
    }


 }

Wenn Sie eine separate Operation im @State benötigen, können Sie am einfachsten eine Zeile hinzufügen: onReceive () zur Ansicht.

  HStack {
        Text("")
            .font(.body)
            .padding(.leading, 10)
        Picker(selection: $selectedOption, label: Text("")) {
            ForEach(0 ..< options.count) {
                Text(self.options[$0]).tag($0)
            }
        }.pickerStyle(SegmentedPickerStyle())
            .padding(.trailing, 25)}
  //        }.onTapGesture {
 //            self.selectedOption = self.selectedOption == 0 ? 1 : 0
 //        }
        .padding(.init(top: 10, leading: 10, bottom: 10, trailing: 0))
        .border(Color.secondary, width: 3)
        .padding(.init(top: 0, leading: 15, bottom: 0, trailing: 15))
        .font(.body)
        .onReceive([self.selectedOption].publisher.first()) { (value) in
            print(value)
    }
E.Coms
quelle
Der Grund, warum didSet für Sie nicht funktioniert, ist, dass Sie die onTapGesture auskommentiert haben. Ich versuche jetzt deine Idee.
Eli Front
Verwenden Sie keine zusätzliche Geste, wenn alles in @State var integriert ist.
E.Coms
Das funktioniert, aber es scheint, dass es einen besseren Weg geben sollte, dies zu tun. Vielen Dank!
Eli Front
5
Dies funktioniert, aber "[self.selectedOption] .publisher.first ()" w00t? :)
sabiland
2
Ist [self.selectedOption].publisher.first()öffentliche API? Es fühlt sich nicht wie eine öffentliche API an, aber verdammt noch mal, es funktioniert.
Iron John Bonney