Terence K
Terence K

Reputation: 41

How to update a UIPickerview after changing it's data source contents

I have 2 UIPickerViews in an ios program which I am running on an iPad simulator. They have one component in each. I find the relevant picker view by using a switch on the tag. The two single component views need to be changed by adding or deleting components. This is easy enough in the data source with pickerData.append(textInput) pickerData.sort() pickerData.reloadAllComponents and pickerData.remove(at: lastDataSelected) picker.reloadAllComponents() where lastDataSelected is the row integer.

This works to change the data source but not entirely when transferred to the UIPickerViews. The UIPickerView display is not updated until I scroll the view. To be more precise, the item selected is correct but the text label is not updated. After scrolling the data labels are all showing correctly. I have tried to programatically scroll from one end to the other but this does not help.

So how can I tell the program to update the view without the user scrolling it? picker.reloadInputViews() does not help.

Apart from this the number of items (rows) isn't changed to reflect the changes in the picker data so the last item falls off the list when adding a new one. So the second question is how to get the UIPickerView functions to update the number of rows?

I haven't been able to find any examples of dynamically updated picker views so hope someone can help or point me in the right direction. The remaining code is fairly standard I believe but I'm obviously missing something in the update process.

override func viewDidLoad() {
    super.viewDidLoad()
    flvPicker = UIPickerView()
    flvPicker.delegate = self
    flvPicker.dataSource = self
    flvPicker.tag = 0
}

func numberOfComponents(in pickerView: UIPickerView) -> Int {
    switch pickerView.tag {
    case 0:
        return 1
    case 1:
        etc...
    }
}
var numberOfRowsInComponent = 0
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
    switch pickerView.tag {
    case 0:
        return flvPickerData.count
    case 1:
        etc...
    }
}
func pickerView(_
    pickerView: UIPickerView,
                titleForRow row: Int, forComponent component: Int) -> String? {
    switch pickerView.tag {
    case 0:
        return flvPickerData[row]
    case 1:
        etc...
    }
}


func pickerView( _ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
    switch pickerView.tag {
    case 0:
        flavourSelected = flvPickerData[row]
        lastFlavourSelected = row
    case 1: etc...
    }
}

I think the question is really how to get the UIPickerView to update correctly after making changes to it's data source and therefore row count.

Upvotes: 1

Views: 2624

Answers (2)

Phontaine Judd
Phontaine Judd

Reputation: 438

A little late to the party, but if you want to update a picker view, there's also the method selectRow. This also has the benefit of an animation property, so you can animate any updates.

Example:

for (index, day) in weeklyOptions[0].enumerated() {
    if scheduledTime.contains(day) {
        weeklyDatePicker.selectRow(index, inComponent: 0, animated: true)
    }
}

Upvotes: 0

alanpaivaa
alanpaivaa

Reputation: 2089

You can use reloadComponent(_:) method from UIPickerView.

Upvotes: 1

Related Questions