Search code examples
iosswiftxcodeuipickerview

Problem using two UIPickerViews - first works, second doesnt


Im trying to use two pickerviews on two different textboxes (i align them underneath the textboxes and hide them until called). I hide the pickerviews until i'm ready to use and tie both textboxes to their corresponding textbox. The first pickerview works fine, but when i click on the second, my list doesnt appear and it appears still hidden. I've read thru the code multiple times and cannot find the issue and have watched multiple videos and checked apples documentation to no avail. Code posted below for review and help. Thanks in advance!

class fifthViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource, UITextFieldDelegate {

    @IBOutlet weak var heightInput: UITextField!
    @IBOutlet weak var weightInput: UITextField!
    @IBOutlet weak var bmiOutput: UITextField!
    @IBOutlet weak var weightPicker: UIPickerView!
    @IBOutlet weak var heightPicker: UIPickerView!

    var height = ["48", "49", "50"]
    var weight = ["90", "91", "92"]

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

    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        var countrows : Int = height.count
        if pickerView == weightPicker {
        countrows = self.weight.count
        }
        return countrows
    }

    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        if pickerView == heightPicker {
        let titleRow = height[row]
            return titleRow
        }
        else if pickerView == weightPicker {
            let titleRow = weight[row]
            return titleRow
        }
        return ""
    }

    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        if pickerView == heightPicker {
            self.heightInput.text = self.height[row]
            self.heightPicker.isHidden = true
        }
        else if pickerView == weightPicker {
            self.weightInput.text = self.weight[row]
            self.weightPicker.isHidden = true
        }
    }

    func textFieldDidBeginEditing(_ textField: UITextField) {
        if (textField == self.heightInput) {
            self.heightPicker.isHidden = false
        }
        else if (textField == self.weightInput) {
            self.weightInput.isHidden = false
        }
    }```

Solution

  • In textFieldDidBeginEditing(), you need to set self.weightPicker.isHidden to false instead of self.weightInput.isHidden.

    func textFieldDidBeginEditing(_ textField: UITextField) {
        if (textField == self.heightInput) {
            self.heightPicker.isHidden = false
        }
        else if (textField == self.weightInput) {
            self.weightPicker.isHidden = false
        }
    }
    

    Modify your code to use inputViews

    I agree with @PaulW11's comment:

    "You would be almost certainly better off if you made the picker views the inputView of each text field."

    Here are the changes you need for a basic setup. Get rid of the pickers in the Storyboard and disconnect the @IBOutlet connections.

    Then add these modifications:

    // These are no longer outlets since they're created in code
    var weightPicker: UIPickerView!
    var heightPicker: UIPickerView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        // set up the picker views
        self.weightPicker = UIPickerView()
        self.weightPicker.delegate = self
        self.weightPicker.dataSource = self
    
        self.heightPicker = UIPickerView()
        self.heightPicker.delegate = self
        self.heightPicker.dataSource = self
    
        self.heightInput.inputView = self.heightPicker
        self.weightInput.inputView = self.weightPicker
    }
    
    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        if pickerView == heightPicker {
            self.heightInput.text = self.height[row]
    
            // make picker go away after value has been selected
            self.heightInput.resignFirstResponder()
        }
        else if pickerView == weightPicker {
            self.weightInput.text = self.weight[row]
    
            // make picker go away after value has been selected
            self.weightInput.resignFirstResponder()
        }
    }