swiftuipickerviewuipickerviewdatasource

Change the 2nd and 3rd pickerView acording to what row from the 1st picker is selected


I have 3 pickers like this: the 1st one is the generalPicker, the 2nd and 3rd are the same. In the generalPicker, I have an array (menu): ["Length", "Volume", "Mass"] and every time I want to choose, for example Mass from the generalPicker, I want to get in the 2nd and 3rd pickers this array: ["Milligram", "Centigram", "Gram", "Kilogram", "Stone", "Pound", "Ounce"].

Or, if I chose in the generalPicker, let's say, Length, then I want to get in the 2nd and 3rd pickers: ["Millimeter", "Centimeter", "Meter", "Kilometer", "Foot", "Yard", "Mile"].

Can anyone give me an idea of how can I actually do that? A sample of my code (the pickers config):

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

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

    if pickerView.tag == 0 || pickerView.tag == 1 {
        return self.pickerLength.count
    } else if pickerView.tag == 2 {
        return self.pickerGeneral1.count
    }

    return 3
}

func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {

    if pickerView.tag == 0 || pickerView.tag == 1{
        return self.pickerLength[row]
    } else if pickerView.tag == 2 {
        return self.pickerGeneral1[row]
    }

    return ""
}

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

    if pickerView.tag == 0  {
        self.pickerTextField.text = self.pickerLength[row]
        self.view.endEditing(true)
    }else if pickerView.tag == 1 {
        self.pickedTextField2.text = self.pickerLength[row]
        self.view.endEditing(true)
    }else if pickerView.tag == 2 {
        self.pickerGeneral.text = self.pickerGeneral1[row]
        self.view.endEditing(true)
    }
}

Arrays defs :

private var pickerMass = ["Milligram", "Centigram", "Gram", "Kilogram", "Stone", "Pound", "Ounce"]
private var pickerVolume = ["Milliliter", "Centiliter", "Liter", "Gallon", "Quart", "Pint", "Fluid ounce"]
private var pickerLength = ["Millimeter", "Centimeter", "Meter", "Kilometer", "Foot", "Yard", "Mile"]
private var pickerGeneral1 = ["Length", "Volume",  "Mass"]

Solution

  • The following is the working code. It is certainly not the pretty way to do the work but will give an idea to resolve the issue.

    class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
    
    @IBOutlet weak var textField_0: UITextField!
    @IBOutlet weak var textField_1: UITextField!
    @IBOutlet weak var textField_2: UITextField!
    
    private var pickerGeneral1 = ["Length", "Volume", "Mass"]
    
    // Maintaining the other arrays as single array of arrays for efficient loading 
    private var subContentArray = [["Millimeter", "Centimeter", "Meter", "Kilometer", "Foot", "Yard", "Mile"],
        ["Milliliter", "Centiliter", "Liter", "Gallon", "Quart", "Pint", "Fluid ounce"],
        ["Milligram", "Centigram", "Gram", "Kilogram", "Stone", "Pound", "Ounce"]]
    
    var picker_0 = UIPickerView()
    var picker_1 = UIPickerView()
    var picker_2 = UIPickerView()
    
    // To keep track of user's current selection from the main content array
    private var _currentSelection: Int = 0
    
    // whenever current selection is modified, we need to reload other pickers as their content depends upon the current selection index only.
    var currentSelection: Int {
        get {
            return _currentSelection
        }
        set {
            _currentSelection = newValue
            picker_1 .reloadAllComponents()
            picker_2 .reloadAllComponents()
    
            textField_0.text = pickerGeneral1[_currentSelection]
            textField_1.text = subContentArray[_currentSelection][0]
            textField_2.text = subContentArray[_currentSelection][0]
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        currentSelection = 0;
    
        picker_0.delegate = self
        picker_0.dataSource = self
        picker_0.tag = 0
    
        picker_1.delegate = self
        picker_1.dataSource = self
        picker_1.tag = 1
    
        picker_2.delegate = self
        picker_2.dataSource = self
        picker_2.tag = 2
    
        textField_0.inputView = picker_0
        textField_1.inputView = picker_1
        textField_2.inputView = picker_2
    }
    
    func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
        return 1
    }
    
    func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        if pickerView.tag == 0 {
            return pickerGeneral1.count
        } else {
            return subContentArray[currentSelection].count
        }
    }
    
    func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        if pickerView.tag == 0 {
            return pickerGeneral1[row]
        } else {
            return subContentArray[currentSelection][row]
        }
    }
    
    func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        if pickerView.tag == 0 {
            currentSelection = row
    
            textField_0.text = pickerGeneral1[row]
            textField_0.resignFirstResponder()
        } else if pickerView.tag == 1 {
            textField_1.text = subContentArray[currentSelection][row]
            textField_1.resignFirstResponder()
        } else if pickerView.tag == 2 {
            textField_2.text = subContentArray[currentSelection][row]
            textField_2.resignFirstResponder()
        }
    }
    }
    

    I would be using only one UIPickerView instead of 3.