How to present JSON array in UIPickerView in alphabetical order?

55 Views Asked by At

I have a UIPickerView that gets data from JSON and presents it in two columns, one that shows two columns, producer and product using the following:

if let url = URL(string: "https://www.example.com/example"),
                let data = try? Data(contentsOf: url),
                let tmpValues = try? JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [[String:String]] {
                let tempCategories = tmpValues?.reduce(into: [String:[String]](), { (dict, value) in
                    if let producer = value["producer"], let product = value["product"] {
                        dict[producer, default:[]].append(product)
                    }
                })
                for category in (tempCategories ?? [:]) {
                    allCategories.append(Category(name: category.key, items: category.value))
                }
                pickerView.reloadAllComponents()
            }

The issue is while the JSON presents the array in alphabetical order, the PickerView presents the array in random orders every time it is opened, how can this be fixed.

2

There are 2 best solutions below

0
vadian On

First of all you are strongly discouraged from loading data from a remote URL with synchronous Data(contentsOf. From the documentation

Important

Don't use this synchronous initializer to request network-based URLs. For network-based URLs, this method can block the current thread for tens of seconds on a slow network, resulting in a poor user experience, and in iOS, may cause your app to be terminated.

Instead, for non-file URLs, consider using the dataTask(with:completionHandler:) method of the URLSession class. See Fetching Website Data into Memory for an example.

Secondly, a dictionary is unordered. You could sort the keys and populate the picker source array this way

if let categories = tempCategories {
    let sortedKeys = categories.keys.sorted()
    allCategories = sortedKeys.map{ Category(name: $0, items: categories[$0]!) }
}
1
Nick  Burinok On

So, before calling:

pickerView.reloadAllComponents()

you can just sort the array

allCategories = allCategories.sorted { $0.name < $1.name }

and it will solve you issue