【问题标题】:Reset the value of the 1st component of UIPickerView when component 0 is changed当组件 0 更改时,重置 UIPickerView 的第一个组件的值
【发布时间】: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() 之前。错误是索引超出范围

标签: arrays swift uipickerview


【解决方案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。
  • 查看第二次崩溃的解决方案的更新答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多