我的UIPickerView遇到了一些同步/图形更新问题。
我想要一个包含两个组件的视图,其中第二个组件的内容取决于第一个组件的选定行。
我的代码灵感来自:Swift UIPickerView 1st component changes 2nd components data
然而,虽然它看起来很有效,但有时(不是每次)会出现一些视觉问题,如下面的屏幕截图所示。(在第二个屏幕截图上,您可以看到第二个组件的行不是真正正确的,而是第一个组件和第二个组件的行的混合)
代码如下:

import UIKit

class AddActivityViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {

    @IBOutlet weak var typePicker: UIPickerView!
    var pickerData: [(String,[String])] = []


    override func viewDidLoad() {
        super.viewDidLoad()

        self.typePicker.delegate = self
        self.typePicker.dataSource = self

        pickerData = [("sport",["bike", "run", "soccer", "basketball"]),
                      ("games",["videogame", "boardgame", "adventuregame"])]

        // not sure if necessary
        typePicker.reloadAllComponents()
        typePicker.selectRow(0, inComponent: 0, animated: false)

//        pickerData = [("sport",["bike", "run", "soccer"]),
//        ("games",["videogame", "boardgame", "adventuregame"])]
    }

    // number of columns in Picker
    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 2
    }

    // number of rows per column in Picker
    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        print("function 1 called")
        if component == 0 {
            return pickerData.count
        } else {
            let selectedRowInFirstComponent = pickerView.selectedRow(inComponent: 0)
            return pickerData[selectedRowInFirstComponent].1.count
        }
    }

    // what to show for a specific row (row) and column (component)
    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        print("function 2 called with values: component: \(component), row: \(row)")
        if component == 0 {
            // refresh and reset 2nd component everytime another 1st component is chosen
            pickerView.reloadComponent(1)
            pickerView.selectRow(0, inComponent: 1, animated: true)

            // return the first value of the tuple (so the category name) at index row
            return pickerData[row].0
        } else {
            // component is 1, so we look which row is selected in the first component
            let selectedRowInFirstComponent = pickerView.selectedRow(inComponent: 0)

            // we check if the selected row is the minimum of the given row index and the amount of elements in a given category tuple array
            print("---",row, (pickerData[selectedRowInFirstComponent].1.count)-1)
            let safeRowIndex = min(row, (pickerData[selectedRowInFirstComponent].1.count)-1)
            return pickerData[selectedRowInFirstComponent].1[safeRowIndex]
        }
        //return pickerData[component].1[row]
    }

    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        // This method is triggered whenever the user makes a change to the picker selection.
        // The parameter named row and component represents what was selected.
    }
}

这是我的代码的问题,还是uipicker的一个复杂方面不能简单地解决?
另外,有没有更好的方法来开发这个功能?
ios - UIPickerView,其中所选的第一个组件确定第二个组件的内容不同步-LMLPHP
ios - UIPickerView,其中所选的第一个组件确定第二个组件的内容不同步-LMLPHP

最佳答案

我解决了这个错误,但是我不明白为什么会这样。
解决方法是修改func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int)方法,我不认为这只是显示字段所必需的。
换句话说,只要把它添加到我现有的代码中:

func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
    if component == 0 {
        pickerView.reloadComponent(1)
    } else {
        let selectedRowInFirstComponent = pickerView.selectedRow(inComponent: 0)

        print(pickerData[selectedRowInFirstComponent].1[row])
    }
}

08-05 08:44