ios - Pickerview 委托(delegate) UIView : array index out of range

标签 ios swift uipickerview

我创建了一个包含 2 个具有不同数据源的组件的选择器 View :

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 View 显示数组,它在第二个组件中显示它们的 subProfessional 值。

错误被触发,例如当我选择信息技术并在第一个组件中选择工程师时,当我滑动第二个组件值时发生错误:

error : fatal error: Array index out of range

编辑:didSelectRow 委托(delegate)中的代码

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()

    }

}

最佳答案

工程师的子职业在其数组中有 4 个值,从您与我们共享的代码中,我可以看出这是唯一可能导致该错误的问题。

如果 UIPickerView 试图在第二个组件中显示第 4 行,它将调用委托(delegate)(如您发布的那样)。在该实现中,您调用 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]
}

编辑

这是一个关于如何改进委托(delegate)实现的示例。 这样,您的代码就不会尝试从错误的数组中获取项目。每次从选取器中选择一个新项目时,您已经重新加载了 pickerView 组件,因此它应该再次调用 DataSource & Delegates。

// 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
}

关于ios - Pickerview 委托(delegate) UIView : array index out of range,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32604547/

相关文章:

objective-c - 什么时候-tableView :cellForRowAtIndexPath: get called?

iPhone UIViewController 中的 UIPickerView

swift - 检测 UIPickerView 何时开始更改/移动

ios - Swift:尽管我调用了所需的代码,但导航栏仍在隐藏?

ios - 自定义多个标签或按钮

ios - 是否可以使用 Swift 创建自定义键盘而不强制用户通过设置屏幕附加它?

swift - 我可以从收到推送通知的设备上删除推送通知吗?

ios - 如何使用 UIPickerView 的选定值作为通知的时间间隔?

android - Phonegap 使用默认阅读器打开 pdf(IOS 和 Android)

Swift - 使用可选的 let