Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI Picker selection binding not updating

I am trying to have a picker list all of a type, called Course and then let the user select the appropriate course when adding a new Assignment to the managed object context. The picker selection binding (courseIndex) isn't updated when the user taps a row in the picker view. I'm not entirely sure how to fix the issue, nor do I know what is causing it. Any help is appreciated!

Here is the affected code:

struct NewAssignmentView: View {

@Environment(\.presentationMode) var presentationMode
@Environment(\.managedObjectContext) var context
@FetchRequest(entity: Course.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \Course.name, ascending: true)]) var courses: FetchedResults<Course>

@State var name = ""
@State var hasDueDate = false
@State var dueDate = Date()
@State var courseIndex = 0


var body: some View {
    NavigationView {
        Form {
            TextField("Assignment Name", text: $name)
            Section {
                Picker(selection: $courseIndex, label:
                    HStack {
                        Text("Course: ")
                        Spacer()
                        Text(self.courses[self.courseIndex].name ?? "").foregroundColor(self.courses[self.courseIndex].color).bold()
                    })
                {
                    ForEach(self.courses, id: \.self) { course in
                        Text("\(course.name ?? "")").foregroundColor(course.color).tag(course)
                    }
                }
            }
            Section {
                Toggle(isOn: $hasDueDate.animation()) {
                    Text("Due Date")
                }
                if hasDueDate {
                    DatePicker(selection: $dueDate, displayedComponents: .date, label: { Text("Set Date:") })
                }
            }
        }
[...]
like image 239
Kevin Olmats Avatar asked Dec 10 '19 23:12

Kevin Olmats


2 Answers

When using optional binding values it's important that you explicitly provide the optional wrapping for the tag values because Swift doesn't automatically unwrap it for you and fails to equate a non-optional value with an optional one.

@Binding var optional: String?

Picker("Field", selection: $optional) {
    // None option.
    Text("None").tag(String?.none)
    // Other fields.
    ForEach(options) { option in
        Text(option).tag(String?.some(option))
    }
}
like image 87
maticzav Avatar answered Nov 13 '22 00:11

maticzav


I cannot make your snapshot compilable, so just changed, here... I assume that as your selection is index, you have to use ranged ForEach instead, like

ForEach(0 ..< self.courses.count) { i in
    Text("\(self.courses[i].name ?? "")").foregroundColor(self.courses[i].color).tag(i)
}

PS. not sure about tag usage, probably it might be not needed.

like image 32
Asperi Avatar answered Nov 13 '22 01:11

Asperi