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

3k Views Asked by At

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"]
2

There are 2 best solutions below

7
Harshit Gupta On BEST ANSWER

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.

0
ppp On

I think you could try using a dictionary instead of arrays. A dictionary of type [ String : String array ] would mean that your dictionary key would hold the category (e.g. Mass) and the value would hold an array of category items (e.g. milligram, centigram - both linked to Mass).

var dictionary: [String:[String]] = 
    [
        "length" : ["Millimeter", "Centimeter", "Meter", "Kilometer", "Foot", "Yard", "Mile"],
        "mass" : ["Milligram", "Centigram", "Gram", "Kilogram", "Stone", "Pound", "Ounce"]
    ]

if let item = dictionary["length"] {
     print(item)
} else {
     print("not found")
}