Did you consider a picker with 3 components ?
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 3
}
Then first component would be populated with car brands
The second would be populated with the entry of the dictionary which lists models
etc…
You set the content in
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
}
Here is a start with just 2 components, you would have to add a third with years of fab
private let brandsNames = [ "Porsche", "Audi", "Ferrari"]
private let modelsDico = [ "Porsche":["911", "Carrera","Cayman"], "Audi": ["i8", "TT"], "Ferrari": ["TestaRossa", "GT"]]
// Dico for years could have entries as "Porsche-911": [1957, 1958]
// Or, if you are sure there are not similar names in 2 different brands, just use the model name as key.
// MARK:- Picker Data Source Methods
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 2 // You will define 3
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
switch component {
case 0 : return brandsNames.count
case 1:
let selected = picker.selectedRow(inComponent: 0)
let selectedName = brandsNames[selected]
return modelsDico[selectedName]?.count ?? 0
default: return 0
}
}
// MARK:- Picker Delegate Methods
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
switch component {
case 0 : return brandsNames[row]
case 1:
let selected = picker.selectedRow(inComponent: 0)
let selectedName = brandsNames[selected]
return modelsDico[selectedName]?[row] ?? ""
default: return ""
}
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
picker.reloadComponent(1) // That reloads the models when you select another brand
}
EDITED for Triple picker (my data are really phony here !):
private let brandsNames = ["Porsche", "Audi", "Ferrari"]
private let modelsDico = [
"Porsche":["911", "Carrera","Cayman"],
"Audi": ["i8", "TT"],
"Ferrari": ["TestaRossa", "GT"]]
// If a model can only exist once !
private let yearsModelsDico = [
"911":[1959, 1960, 1961], "Carrera": [1970,1971], "Cayman": [2000,2001],
"i8":[2010, 2011], "TT": [2000,2001],
"TestaRossa":[2002, 2003], "GT": [1990,1991, 1992, 1993]]
// MARK:- Picker Data Source Methods
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 3
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
switch component {
case 0 : return brandsNames.count
case 1:
let selected = picker.selectedRow(inComponent: 0)
let selectedName = brandsNames[selected]
return modelsDico[selectedName]?.count ?? 0
case 2:
let selectedBrand = picker.selectedRow(inComponent: 0)
let selectedBrandName = brandsNames[selectedBrand]
let selectedModel = picker.selectedRow(inComponent: 1)
let selectedModelName = modelsDico[selectedBrandName]?[selectedModel] ?? ""
return yearsModelsDico[selectedModelName]?.count ?? 0
default: return 0
}
}
// MARK:- Picker Delegate Methods
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
switch component {
case 0 : return brandsNames[row]
case 1:
let selected = picker.selectedRow(inComponent: 0)
let selectedName = brandsNames[selected]
return modelsDico[selectedName]?[row] ?? ""
case 2:
let selectedBrand = picker.selectedRow(inComponent: 0)
let selectedBrandName = brandsNames[selectedBrand]
let selectedModel = picker.selectedRow(inComponent: 1)
let selectedModelName = modelsDico[selectedBrandName]?[selectedModel] ?? ""
return String(yearsModelsDico[selectedModelName]?[row] ?? 0)
default: return ""
}
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if component == 0 {
picker.reloadComponent(1)
picker.reloadComponent(2)
}
if component == 1 {
picker.reloadComponent(2)
}
}