Hi! I am working on a pickerView with two components. I have an array (myHorses) with one stallion and two mares. If I run the app I get an "out of range" error at line 33. If I add another stallion to the array this goes away. Also, the image outlets are showing the images for the stallion on both outlets. How can I make the app work when there is just one member of a gender, and also show the correct images?
Code Block import UIKit class BreedingViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource { let myStallions = myHorses.filter({ $0.gender == "Stallion" }) let myMares = myHorses.filter({ $0.gender == "Mare" }) var sireIndex = 0 var damIndex = 0 @IBOutlet weak var horsePicker: UIPickerView! @IBOutlet weak var sireBaseLayer: UIImageView! @IBOutlet weak var damBaseLayer: UIImageView! var recievedString: String = "" func numberOfComponents(in sirePicker: UIPickerView) -> Int { return 2 } func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { if component == 0 { return myStallions.count } else { return myMares.count } } func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { let stallions = myStallions[row] let mares = myMares[row] if component == 0 { return "\(stallions.name), health: \(stallions.health)" } else { return "\(mares.name), health: \(mares.health)" } } func pickerView(_ horsePicker: UIPickerView, didSelectRow row: Int, inComponent component: Int) { var chosenSire = myHorses[sireIndex] var chosenDam = myHorses[damIndex] if component == 0 { let theSire = myHorses[row] sireNameOutlet.text = theSire.name chosenSire = theSire sireBaseLayer.image = chosenSire.basePhenotype } else { let theMare = myHorses[row] damNameOutlet.text = theMare.name chosenDam = theMare damBaseLayer.image = chosenDam.basePhenotype } } override func viewDidLoad() { super.viewDidLoad() horsePicker.delegate = self horsePicker.dataSource = self } }
As far as I see the definition of your pickerView(_ :numberOfRowsInComponent:),
row in your pickerView(_:titleForRow:forComponent:) will take arbitrary number in range:
To make two methods consistent, your pickerView(_:titleForRow:forComponent:) should be something like this:
You may also need to fix pickerView(_:didSelectRow:inComponent:), but it seems not complete yet. So, it would be another issue in the future.
row in your pickerView(_:titleForRow:forComponent:) will take arbitrary number in range:
0..<myStallions.count when component == 0
0..<myMares.count otherwise
To make two methods consistent, your pickerView(_:titleForRow:forComponent:) should be something like this:
Code Block func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { if component == 0 { let stallions = myStallions[row] return "\(stallions.name), health: \(stallions.health)" } else { let mares = myMares[row] return "\(mares.name), health: \(mares.health)" } }
You may also need to fix pickerView(_:didSelectRow:inComponent:), but it seems not complete yet. So, it would be another issue in the future.