Reputation: 1
I have a label that I want programmatically add a birthdate from my user, I manage to populate with data, but I can't extract data correctly, here is my code: that show an error like the index is out of range, and crash my app
class SignUpFormViewController: UIViewController {
let date = Date()
let formatter = DateFormatter()
let years = (1800...2100).map{String($0)}
let days = (1...31).map{String($0)}
var pickerMonth: [String] = [String]()
var pickerDay: [String] = [String]()
var pickYears: [String] = [String]()
var selectedMonth: String?
var selectedDay: String?
var selectedYear: String?
//other stuff
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
handleGestureRecognizer()
self.datePickerView.delegate = self
self.datePickerView.dataSource = self
datePickerComponents()
}
}
extension SignUpFormViewController: UIPickerViewDelegate, UIPickerViewDataSource {
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 3
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if component == 0 {
return pickerMonth.count//month
}else if component == 1 {
return pickerDay.count//day
}else {
return pickYears.count//year
}
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if component == 0 {
return pickerMonth[row]
}else if component == 1 {
return pickerDay[row]
}else {
return pickYears[row]
}
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
birthDateTextField.text = "\(pickerMonth[row])/\(pickerDay[row])/\(pickYears[row])"
}
func datePickerComponents() {
pickerMonth = formatter.shortMonthSymbols
pickerDay = days
pickYears = years
}
}
Upvotes: 0
Views: 55
Reputation: 534885
The problem is here:
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
birthDateTextField.text = "\(pickerMonth[row])/\(pickerDay[row])/\(pickYears[row])"
}
That's way too simple-minded. Think about it. The user spins only one component at a time, and your method is called. Let's say it's the year component that the user spun. You've got 300 of those. So row
could be 300 (let's say). But pickerMonth
doesn't have 300 months in it! So you crash when you naively say pickerMonth[row]
.
What you want to do is ask the picker view what row is selected in all three components and use that row for that component.
birthDateTextField.text =
pickerMonth[pickerView.selectedRow(inComponent:0)]
+ "/" +
pickerDay[pickerView.selectedRow(inComponent:1)]
+ "/" +
pickYears[pickerView.selectedRow(inComponent:2)]
Upvotes: 1