Pickerview委托UIView:数组索引超出范围

时间:2015-09-16 09:23:05

标签: ios swift uipickerview

我使用具有不同数据源的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()

    }

}

1 个答案:

答案 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
}