7

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

asked Nov 10, 2014 at 10:28
2
  • Experiencing the same problem at the moment Commented Mar 18, 2015 at 9:52
  • Which version of Xcode are you using? Commented Mar 18, 2015 at 10:15

1 Answer 1

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)
}
answered Nov 10, 2014 at 11:56
1
  • 3
    I'm not sure if you're serious about this, but I tried it anyway. It doesn't make any difference. Commented Nov 10, 2014 at 16:15

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.