Search code examples
iosswiftuipickerview

How to disable a button when the 1st row in a custom picker view is selected?


I have a custom UIPickerView class (also conforms to UIPickerViewDelegate, UIPickerViewDataSource) that is used in 2 view controllers. So in both of them I have this: myPickerView.delegate = myPickerView and same with dataSource. All the rows and components are configured in that custom picker view class.

I want to disable a button in my VCs when the 1st row is selected. Usually I would do this by using one of the picker view's delegate functions (pickerView(_:,didSelectRow:, inComponent:), but since I use a custom one that already conforms to UIPickerViewDelegate, I can't do that.


Solution

  • Hmm, tricky. The issue is that the picker is its own delegate, which makes the solution a bit complicated, but here's what I might do: give the picker a closure that gets called when the selected row changes. Then call that closure from the delegate method.

    class MyPickerView {
        typealias SelectedIndexClosure = (Int) -> Void
        var selectedIndexClosure: SelectedIndexClosure = { _ in }
    
    ...
    
        func picker(_ picker: UIPickerView, didSelectRow row: Int ...) {
            selectedIndexClosure(row)
        }
    }
    

    Then you'd set the selectedIndexClosure to whatever code you want to be run in the view controller.

    myPickerView.selectedIndexClosure = { [weak self] index in
        self?.button.enabled = (index == 1)
    }
    

    And that should do. An more idiomatic solution might be to refactor the picker's datasource and delegate methods into a new, separate object owned by the view controller, but this should work fine.