I have a really strange issue. I'm sorting an array of NSDictionary objects in my app, but it only works correctly when the app is running from Xcode. As soon as I distribute the app and install & run it on a device, the sorting no longer works.
Here's the code can be run in a playground, with some example NSDictionary objects. The code in the app is the same.
import UIKit
let p1 = NSDictionary(objects: ["Zoe", 32], forKeys: ["name", "age"])
let p2 = NSDictionary(objects: ["Adrian", 54], forKeys: ["name", "age"])
let p3 = NSDictionary(objects: ["Jeff", 23], forKeys: ["name", "age"])
let p4 = NSDictionary(objects: ["", 66], forKeys: ["name", "age"])
let p5 = NSDictionary(objects: [23], forKeys: ["age"])
let persons = [p1,p2,p3,p4,p5]
let sortedPersons = persons.sorted { (p1, p2) -> Bool in
(p2["name"] as? String) > (p1["name"] as? String)
}
As you can see, sorting in the playground does work correctly. Does anyone know what could be wrong?
Update
I found that the Swift Optimization Level is causing the problem. Setting this to -O
(Fastest) will cause the sort to fail. Setting it to -Onone
(None) will cause the sort to work properly.
Does anyone have any suggestions on how to change the code, so it will work with -O
optimization?
Update 2
I've filed a bug report at Apple. For the time being I'm using an NSSet
to sort the array, which seems to be working fine.
Last update
I haven't been able to reproduce this since Xcode 6.1.1
-
Experiencing the same problem at the momentsachadso– sachadso2015年03月18日 09:52:39 +00:00Commented Mar 18, 2015 at 9:52
-
Which version of Xcode are you using?René– René2015年03月18日 10:15:04 +00:00Commented Mar 18, 2015 at 10:15
1 Answer 1
This appears to be down to your naming convention within your sorted closure. Changing (p1, p2) to different names will resolve it. With -Ofastest, the compiler seems to be incorrectly doing 2 things:
1) causing p1 and p2 within the closure to refer to the NSDictionarys themselves rather than the closure parameters
2) cleaning up the references to the NSDictionary objects prematurely, given #1
Change the code so the last section shows:
let sortedPersons = persons.sorted { (d1, d2) -> Bool in
(d2["name"] as? String) > (d1["name"] as? String)
}
-
3I'm not sure if you're serious about this, but I tried it anyway. It doesn't make any difference.René– René2014年11月10日 16:15:49 +00:00Commented Nov 10, 2014 at 16:15