UIPickerView

UIPickerView a view that uses a spinning-wheel to show one or more sets of values.

UIDatePicker built-in control based on UIPickerView to select date and time. Since iOS 14+ you can select other style, not only wheel.

UIPickerViewDataSource provides information about data:

  • numberOfComponents(UIPickerView) - the number of components (i.e. columns).
  • pickerView(UIPickerView, numberOfRowsInComponent: Int) - the number of rows for a specified component.

UIPickerViewDelegate allows to specify size and content of items. Most useful methods:

  • pickerView(UIPickerView, titleForRow, forComponent) - provides title to use for a given row in a given component.
  • pickerView(UIPickerView, didSelectRow, inComponent) - called by the picker view when the user selects a row in a component.
Infinite UIPickerView
class MyViewController: UIViewController {

    private let pickerViewData = ["title_1", "title_2", ..., "title_n"] 
    private let pickerViewRows = 100_000
    private let pickerViewMiddle = 
            ((pickerViewRows / pickerViewData.count) / 2) * pickerViewData.count

    // ...
    
    override func viewDidLoad() {
        self.picker.delegate = self
        self.picker.dataSource = self
        
        let initialValue = 0
        if let row = rowForValue(initialValue) {
            self.picker.selectRow(row, inComponent: 0, animated: false)
        }
    }
}

extension MyViewController : UIPickerViewDataSource {
   
    func rowForValue(value: Int) -> Int? {
        if let valueIndex = find(pickerViewData, value) {
            return pickerViewMiddle + value
        }
        return nil
    }

    func pickerView(pickerView: UIPickerView, 
                    titleForRow row: Int, 
                    forComponent component: Int) -> String! {
        
        // use % for looping  
        return "\(pickerViewData[row % pickerViewData.count])"
    }
}

extension MyViewController : UIPickerViewDelegate {

    func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
        return 1
    }

    func pickerView(pickerView: UIPickerView, 
                    numberOfRowsInComponent component: Int) -> Int {
        return pickerViewRows
    }

    func pickerView(pickerView: UIPickerView, 
                    didSelectRow row: Int, 
                    inComponent component: Int) {
        // ...

        // reset current item 
        // to the closest to the middle
        let newRow = pickerViewMiddle + (row % pickerViewData.count)
        pickerView.selectRow(newRow, inComponent: 0, animated: false)
    }

}