I'm having a heck of a time in Swift 3 sorting an array of dictionaries.
In Swift 2, I would do it this way, which worked fine:
var dicArray = [Dictionary<String, String>()]
let dic1 = ["last": "Smith", "first": "Robert"]
dicArray.append(dic1)
let dic2 = ["last": "Adams", "first": "Bill"]
dicArray.append(dic2)
let sortedArray = dicArray.sort { ($0["last"] as? String) < ($1["last"] as? String) }
Converting the same code to Swift 3 has not gone well. The system guided me to this (through a circuitous route):
let sortedArray = dicArray.sorted { ($0["last"]! as String) < ($1["last"]! as String) }
But the app always crashes, with the error that it found nil while unwrapping an Optional value.
After banging my head against the table for too long, putting ?s and !s in every imaginable combination, I resorted to an old approach to get the job done:
let sortedArray = (dicArray as NSArray).sortedArray(using: [NSSortDescriptor(key: "last", ascending: true)]) as! [[String:AnyObject]]
That works, and I'm moving along, but it's not very Swifty, is it?
Where did it all go wrong? How can I make the pure Swift sort function work in a case like this?
Where did it all go wrong?
It went wrong on your first line:
var dicArray = [Dictionary<String, String>()]
That never did what you want, even in Swift 2, because you are actually inserting an extra, empty dictionary into the array. That's where the crash comes from; the empty dictionary has no "last"
key, because it is, uh, empty.
You want this:
var dicArray = [Dictionary<String, String>]()
See the difference? After that change, everything falls into place:
var dicArray = [Dictionary<String, String>]()
let dic1 = ["last": "Smith", "first": "Robert"]
dicArray.append(dic1)
let dic2 = ["last": "Adams", "first": "Bill"]
dicArray.append(dic2)
let sortedArray = dicArray.sorted {$0["last"]! < $1["last"]!}
// [["first": "Bill", "last": "Adams"], ["first": "Robert", "last": "Smith"]]