我使用具有不同数据源的2个组件创建了一个选择器视图:
func pickerView(pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusingView view: UIView?) -> UIView {
let pickerLabel = UILabel()
let titleLabel = firstFieldArray[row]
let titlelabel2 = secondFieldArray[row]
if component == 0 {
let myTitle = NSAttributedString(string: titleLabel, attributes: [NSFontAttributeName:UIFont(name: "Georgia", size: 15.0)!,NSForegroundColorAttributeName:UIColor.blackColor()])
pickerLabel.attributedText = myTitle
} else {
let myTitle = NSAttributedString(string: titlelabel2, attributes: [NSFontAttributeName:UIFont(name: "Georgia", size: 15.0)!,NSForegroundColorAttributeName:UIColor.blackColor()])
pickerLabel.attributedText = myTitle
}
return pickerLabel
}
这是我的数据模型:
class professionArrays {
func professsionValues() -> [String] {
return ["Engineer", "Information Technology", "Teacher"]
}
func subProfessionValues(profession: String) -> [String] {
if profession == "Engineer" {
return ["Electrical Engineer","Sex Engineer","Civil Engineer","Software Engineer"]
} else if profession == "Information Technology" {
return ["IT Programmer","UI/UX Designer","Tester/Debugger"]
} else {
return ["English Teacher", "Math Teacher", "Physics Teacher"]
}
}
}
当我选择Engineer,Information Technology和Teacher时,Picker视图显示数组,它在第二个组件中显示其subProfessional值。
触发错误,例如当我选择信息技术并在第一个组件中选择工程师时,当我滑动第二个组件值时会发生错误:
错误:致命错误:数组索引超出范围
编辑:didSelectRow委托内的代码
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if component == 0 {
let professionAndSubProfession = professionArrays()
let currentValue = firstFieldArray[row]
secondFieldArray = professionAndSubProfession.subProfessionValues(currentValue)
pickerView.reloadAllComponents()
firstProfessionCurrentValue = firstFieldArray[row]
print(firstProfessionCurrentValue)
selectedProfessionLabel.text = firstProfessionCurrentValue
professionTextfield.text = firstProfessionCurrentValue
} else {
secondSubProfessionCurrentValue = secondFieldArray[row]
selectedSubProfessionLabel.text = secondSubProfessionCurrentValue
professionTextfield.text = "\(firstProfessionCurrentValue!) - \(secondSubProfessionCurrentValue!)"
print(secondSubProfessionCurrentValue)
pickerView.reloadAllComponents()
}
}
答案 0 :(得分:1)
工程师的子专业人员在其数组中有4个值,并且根据您与我们共享的代码,我可以看到这是唯一可能产生该错误的问题。
如果UIPickerView尝试在第二个组件中显示第4行,它将调用该委托(如您发布的那样)。在该实现中,您调用firstFieldArray [row]。那时行是3,但是firstFieldArray只有3个值,因此它的最大索引在那时是2。
简而言之,如果组件为1,则不要创建titleLabel,否则,如果组件为0,则不创建titleLabel2。如果您不确定数组是否保留该数量你尝试获得索引的值,做一些防御性编码:
// Check if the array holds the same or more values then 'row'
if array.count > row {
return array[row]
}
修改强>
以下是有关如何改进代理实施的示例。 通过这种方式,您的代码不会尝试从错误的数组中获取项目。每次从选择器中选择一个新项时,您都已经重新加载了pickerView组件,所以它应该调用DataSource&再次代表。
// UIPickerViewDataSource
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int
if component == 0 {
return firstFieldArray.count
} else {
return secondFieldArray.count
}
}
//UIPickerViewDelegate
func pickerView(pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusingView view: UIView?) -> UIView {
let pickerLabel = UILabel()
if component == 0 {
// By placing it within the if-statement, this array won't be searched by index unnecassary.
// So even if the second component would hold 4 or more items, it won't try to fetch 4th or higher index from this first array.
let titleLabel = firstFieldArray[row]
let myTitle = NSAttributedString(string: titleLabel, attributes: [NSFontAttributeName:UIFont(name: "Georgia", size: 15.0)!,NSForegroundColorAttributeName:UIColor.blackColor()])
pickerLabel.attributedText = myTitle
} else {
let titlelabel2 = secondFieldArray[row]
let myTitle = NSAttributedString(string: titlelabel2, attributes: [NSFontAttributeName:UIFont(name: "Georgia", size: 15.0)!,NSForegroundColorAttributeName:UIColor.blackColor()])
pickerLabel.attributedText = myTitle
}
return pickerLabel
}