当组件 0 更改时,重置 UIPickerView 的第一个组件的值

Posted

技术标签:

【中文标题】当组件 0 更改时,重置 UIPickerView 的第一个组件的值【英文标题】:Reset the value of the 1st component of UIPickerView when component 0 is changed 【发布时间】:2019-04-28 19:27:07 【问题描述】:

当组件 0 更改时,我无法弄清楚如何将 PickerView 的第一个组件中使用的数组重置为组件 0(以避免由于 indexOutOfRange 导致的可能错误)。

这是我的数据结构

let bananas = ["banana1", "banana2"]
let fruitArray = ["banana1" : ["cherry1","cherry2"], "banana2" : ["cherry1", "cherry2", "cherry3"]]


func numberOfComponents(in pickerView: UIPickerView) -> Int 
    return 2


func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int 
    if component == 0 
        return bananas.count
    
    else 
        let selectedBanana = pickerView.selectedRow(inComponent: 0)
        return fruitArray[banana[selectedBanana]]!.count
    


func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) 


    let selectedBanana = pickerView.selectedRow(inComponent: 0)
    let selectedCherry = pickerView.selectedRow(inComponent: 1)


    bananaPicked = bananas[selectedBanana]
    cherryPicked = fruitArray[bananaPicked]![selectedCherry]


    pickerView.reloadAllComponents() 
    


func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? 
if component == 0 
    return bananas[row]

else 
    let selectedBanana = pickerView.selectedRow(inComponent: 0)
    return fruitArray[selectedBanana]![row]


现在,当我(假设)在香蕉 2 和樱桃 3 中,但我切换到香蕉 1 时,我得到一个 indexOutOfRange 错误,因为当然第一个香蕉数组没有第三个项目。每当香蕉行更改为樱桃行重置为 0 时,我都希望它。

__________ 更新 ______________ 这是我发现的另一个导致崩溃的错误(indexOutOfRange),我发布了一个屏幕截图。

【问题讨论】:

pickerView.selectedRow(inComponent: 0) 返回 Int 值。但是你的fruitArray 是一个字典 哪一行导致错误? @AhmetSinaUstem 之后的行我应该使用该 Int 访问列表中精确位置的项目(作为字典中的值,使用键香蕉) @rmaddy 导致错误的行是cherryPicked = fruitArray[bananaPicked]![selectedCherry],在 reloadAllComponents() 之前。错误是索引超出范围 【参考方案1】:

当组件 0 改变时,将组件 1 中的选中行设置为 0。

此外,无需重新加载所有组件。只有组件 1 需要重新加载。

func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) 

    if component == 0 
        pickerView.selectRow(0, inComponent: 1, animated: false)
    

    let selectedBanana = pickerView.selectedRow(inComponent: 0)
    let selectedCherry = pickerView.selectedRow(inComponent: 1)

    bananaPicked = bananas[selectedBanana]
    cherryPicked = fruitArray[bananaPicked]![selectedCherry]

    //pickerView.reloadAllComponents()
    pickerView.reloadComponent(1)

对于第二次崩溃,尝试一些防御性编程来避免崩溃:

func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? 
    if component == 0 
        return bananas[row]
    
    else 
        let selectedBanana = pickerView.selectedRow(inComponent: 0)
        let rowData = fruitArray[bananas[selectedBanana]]!
        if rowData.indices.contains(row) 
            return rowData[row]
         else 
            return nil
        
    

【讨论】:

谢谢。那解决了它。由于我现在只是在测试应用程序,我遇到了另一个导致它崩溃的问题。我刚刚尝试随机滚动选择器的组件 0,同时滚动组件 1。它突然崩溃了。除了将屏幕上可能的触摸限制为一个之外,您认为还有其他方法可以解决它吗?谢谢 同样,它是在 titleForRow 内的 return fruitArray[selectedBanana]![row] 行中超出范围的索引。我观察到,当组件 0 在第一行上方选择时发生这种情况,而组件 1 正在向下滚动。 是不是因为组件0的索引是-1? 我刚刚检查了该值,它发生在以下行中(等效于本例中) selectedBanana = 0 和 row = 2: return fruitArray[selectedBanana]![row] 。可能仍然是因为和以前一样的错误,但如果我做得太快并且同时它没有时间重置为 0。 查看第二次崩溃的解决方案的更新答案。

以上是关于当组件 0 更改时,重置 UIPickerView 的第一个组件的值的主要内容,如果未能解决你的问题,请参考以下文章

如何将 UIPickerView 重置为索引:0,iPhone

UIPickerView 重新加载组件不起作用

相互切换2个UIPickerview的组件

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

当 UIPickerView 值更改时,表行在 ios 中更改

Swift UIPickerView 第一个组件更改第二个组件数据