0

I have a SwiftUI Picker and I want to update another view based on its value as the user scrolls through the list. By passing a @Binding to the picker I can update when the user stops on a selected item... but I haven't been able to find an event that fires as the list scrolls.

With the old UIPickerView you can use titleForRow to hook into this as mentioned in this answer. I'm looking for something similar that works with SwiftUI's Picker.

Here's an extremely simple SwiftUI snippet that demonstrates the problem with the default behavior that I'm trying to find a way to work around:

import SwiftUI

struct ContentView: View {
    @State var selected:Int = 0
    var toDisplay:String {
        get {
            return "Selected: \(selected)"
        }
    }
    var body: some View {
        return VStack {
            Text(toDisplay)
            Form {
                Section{
                    Picker(selection: $selected, label: Text("")) {
                        ForEach(0..<100) {
                            Text("Item \($0)").tag($0)
                        }
                    }
                    .pickerStyle(WheelPickerStyle())
                    .frame(width: 350, height: 250, alignment: .center)
                }
            }
        }
    }
}

#if DEBUG
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
#endif

If you run this, you can see that the Selected: # text at the top doesn't update until the picker completely stops:

picker delay

Brad Dwyer
  • 6,305
  • 8
  • 48
  • 68
  • The original `UIPickerView` behaves exactly like this also. – Mojtaba Hosseini Aug 13 '19 at 21:51
  • The link you mention using `titleForRow` with UIPickerView is a hack since `titleForRow` is called many times and it's not necessarily for the row passing through the center of the picker view. – rmaddy Aug 13 '19 at 23:33
  • I’d be fine with a “hacky” solution. I just don’t want to have to completely rebuild my own custom version of `Picker` just for this. – Brad Dwyer Aug 14 '19 at 12:34

1 Answers1

2

If you’re looking for a way to achieve this using only SwiftUI’s Picker, then I believe you’re out of luck. Because of how SwiftUI is designed, you really don’t have access to the underlying functionality of these views in the same way you would with UIKit. If you think that using titleForRow with a UIPickerView is a viable solution, then your best bet would be to use UIViewRepresentable to port UIPickerView over to use with SwiftUI.

graycampbell
  • 7,430
  • 3
  • 24
  • 30