0

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.

John
  • 965
  • 8
  • 16
  • what's not ordered? categories presented by dictionary, or values within each category presented by array? or both? – timbre timbre Sep 10 '19 at 16:29
  • Show the appropriate picker view data source/delegate methods. And show your attempt to properly sort the array you use to populate the picker view. – rmaddy Sep 10 '19 at 16:29

2 Answers2

1

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]!) }
}
Community
  • 1
  • 1
vadian
  • 274,689
  • 30
  • 353
  • 361
1

So, before calling:

pickerView.reloadAllComponents()

you can just sort the array

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

and it will solve you issue