UIPickerView, где выбранный 1-й компонент решает, что содержимое 2-го компонента не синхронизировано - PullRequest
1 голос
/ 17 октября 2019

Я столкнулся с некоторыми проблемами синхронизации / обновления графики с моим UIPickerView.

Я хочу представление с 2 компонентами, где содержимое второго компонента зависит от выбранной строки первого компонента.

Мой код основан на: Swift UIPickerView 1-й компонент изменяет данные 2-х компонентов

Однако, хотя кажется, что это работает, иногда (не каждый раз) возникают некоторые визуальные проблемы, так каквидно на скриншотах ниже. (на втором снимке экрана вы можете видеть, что строки второго компонента не совсем корректны и представляют собой сочетание строк первого и второго компонента)

Вот код:

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

Это проблема с моим кодом или вообще сложный аспект UIPickers, который не может быть тривиально решен?

Кроме того, есть ли лучший способ развить эту функциональность?

initial view

view out of sync

1 Ответ

0 голосов
/ 17 октября 2019

Я решил ошибку, однако не понимаю, почему это решает ее.

Решение состоит в том, чтобы реализовать метод 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])
    }
}
...