Search code examples
iosswiftuipickerview

Issue with adding second UIPickerView on the same view ViewController


Essentially I simply want to add a second UIPickerView to my ViewController but do not understand why the following code does work properly.

When selecting the second text field stopTextField I expect the stopPicker UIPickerView show up, but instead the same gradePicker UIPickerView comes up.

It seems to compile fine, but completely ignores:

let stopPickerValues = ["What Stop?","Stop 1", "Stop 2", "Stop 3", "Stop 4", "Stop 5", "Stop 6", "Stop 7", "Stop 8", "Stop 9", "Stop 10"]

What is the issue?

Here is the code:

import UIKit

class timeselectviewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
    @IBOutlet weak var gradeTextField: UITextField!
    @IBOutlet weak var stopTextField: UITextField!


    var gradePicker: UIPickerView!
    var stopPicker: UIPickerView!

    let gradePickerValues = ["select approximate arrival time","8:00 am -12:00 pm", "12:00 pm - 4:00 pm", "4:00 pm - 8:00 pm"]

    let stopPickerValues = ["What Stop?","Stop 1", "Stop 2", "Stop 3", "Stop 4", "Stop 5", "Stop 6", "Stop 7", "Stop 8", "Stop 9", "Stop 10"]

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

    func numberOfComponents2(in pickerView2: UIPickerView) -> Int {
        return 1
    }

    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int{
        return gradePickerValues.count
    }

    func pickerView2(_ pickerView2: UIPickerView, numberOfRowsInComponent2 component2: Int) -> Int{
        return stopPickerValues.count
    }

    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        return gradePickerValues[row]
    }

    func pickerView2(_ pickerView2: UIPickerView, titleForRow2 row2: Int, forComponent2 component2: Int) -> String? {
        return stopPickerValues[row2]
    }

    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        gradeTextField.text = gradePickerValues[row]
        self.view.endEditing(true)
    }

    func pickerView2(_ pickerView2: UIPickerView, didSelectRow2 row2: Int, inComponent2 component2: Int) {
        stopTextField.text = stopPickerValues[row2]
        self.view.endEditing(true)
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        gradePicker = UIPickerView()
        stopPicker = UIPickerView()
        gradePicker.dataSource = self
        stopPicker.dataSource = self
        gradePicker.delegate = self
        stopPicker.delegate = self

        stopTextField.inputView = stopPicker
        gradeTextField.inputView = gradePicker
        gradeTextField.text = gradePickerValues[0]
        stopTextField.text = stopPickerValues[0]
    }
}

Solution

  • You can do this:

    var pickerView: UIPickerView!
    
    ...
    
    
    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int{
      if gradeTextField.isFirstResponder {
        return gradePickerValues.count
      } else {
        return stopPickerValues.count
      }
    }
    
    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
      if gradeTextField.isFirstResponder {
        return gradePickerValues[row]
      } else {
        return stopPickerValues[row]
      }
    }
    
    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
      if gradeTextField.isFirstResponder {
        gradeTextField.text = gradePickerValues[row]
      } else {
        stopTextField.text = stopPickerValues[row]
      }
      self.view.endEditing(true)
    }
    
    override func viewDidLoad() {
      super.viewDidLoad()
    
      pickerView = UIPickerView()
      pickerView.dataSource = self
      pickerView.delegate = self
    
      stopTextField.inputView = pickerView
      gradeTextField.inputView = pickerView
      gradeTextField.text = gradePickerValues[0]
      stopTextField.text = stopPickerValues[0]
    }
    

    The thing is your pickerView2 methods are just being ignored. That way I posted above checks which text field is the first responder to perform the required actions or return the proper values.

    EDIT

    As pointed out by rmaddy, you only need one picker view, since you can only have one text field as first responder at a time.