Search code examples
iosswiftuipickerview

How can I populate a picker view depending on the selection of another picker view in Swift?


Looking for a solution to populate a picker view depending on the selection of another picker view within the same view controller. The first selects a category. The second the items of that category.

Here's what I (Swift beginner) came up with:

import UIKit

class ViewController: UIViewController, UIPickerViewDataSource,      UIPickerViewDelegate {

var countryClasses = ["US", "EU", "JP"]
var usItems = ["usitem1", "usitem2", "usitem3", "usitem4", "usitem5"]
var euItems = ["euitem1", "euitem2", "euitem3", "euitem4", "euitem5"]
var jpItems = ["jpitem1", "jpitem2", "jpitem3", "jpitem4", "jpitem5"]

@IBOutlet weak var countryPicker: UIPickerView!

@IBOutlet weak var itemPicker: UIPickerView!

override func viewDidLoad() {
    super.viewDidLoad()
    self.countryPicker.dataSource = self;
    self.countryPicker.delegate = self;
    self.itemPicker.dataSource = self;
    self.itemPicker.delegate = self;
}

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

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

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

}


Solution

  • As both the Pickers are using the same delegate you are going to need a way to identify them when your delegate methods run, also your current Array structure means you are going to need a way to select each item array as and when the country is selected.

    Create a store for the selected item array.

    var selectedItemsArray = []
    

    Add some checks to your delegate methods.

    func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
        return 1
    }
    
    func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        if pickerView == countryPicker {
            return countryClasses.count
        } else if pickerView == itemPicker {
            return selectedItemsArray.count
        }
        return 0
    }
    
    func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
        if pickerView == countryPicker {
            return countryClasses[row]
        } else if pickerView == itemPicker {
            return selectedItemsArray[row]
        }
        return 0
    }
    

    Then you need to implement did Select row to setup the item store and reload the data.

    func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        if pickerView == countryPicker {
            switch row {
            case 0:
                selectedItemsArray = usItems
            case 1:
                selectedItemsArray = euItems
            case 2:
                selectedItemsArray = jpItems
            default:
                selectedItemsArray = []  
            }
            // IMPORTANT reload the data on the item picker
            itemPicker.reloadAllComponents()
        } else if pickerView == itemPicker {
            // Get the current item
            var item = selectedItemsArray[row]
            // Assign value to a label based on which array we are using
            if selectedItemsArray == usItems {
                usLabel.text = item
            } else if selectedItemsArray == euItems {
                euLabel.text = item
            } else if selectedItemsArray == jpItems {
                jpLabel.text = item
            }
        }
    }
    

    I haven't tested this code, but the logic should be correct.