Zipette
Zipette

Reputation: 79

Swift 2.x to swift 3, XCode complaining error : Type of expression is ambiguous without more context

Here is my swift 2.X code that does'nt work any more on swift 3 :

var dictThemesNamesStyles=[String:[Int:Int]]()
self.styles=dictThemesNamesStyles
let keysArray:Array=Array(self.styles.keys)
let sortedKeysArray = keysArray.sorted(by:
{
    (str1: NSObject, str2: NSObject) -> Bool in
    return Int((str1 as! String))<Int((str2 as! String))
})
self.stylesLevel1Keys=sortedKeysArray
self.styleThemesPickerView.reloadAllComponents()

On line : "return Int((str1 as! String)) < Int((str2 as! String))" it complains with the error : "Type of expression is ambiguous without more context"

What do I have to change in this code to make it work ? Thanks a lot.

Upvotes: 0

Views: 243

Answers (2)

Charles Srstka
Charles Srstka

Reputation: 17060

Let's go through this line by line:

var dictThemesNamesStyles=[String:[Int:Int]]()
self.styles=dictThemesNamesStyles

Okay, we've got a dictionary of strings to dictionaries of integers.

let keysArray:Array=Array(self.styles.keys)

There are a few problems with this line:

  1. The declaration of :Array without a generic parameter.

  2. The type declaration is unnecessary, since the type system already knows this is an Array, since you're calling Array's initializer.

  3. Creating this whole Array is unnecessary, since we're just passing the result to sorted, which already exists on the collection returned by keys, and which will return an Array. Creating the array is therefore a needless performance hit which we should avoid.

I would, in fact, delete this entire line, and just replace keysArray with self.styles.keys in the next line:

let sortedKeysArray = self.styles.keys.sorted(by:

Next:

{
    (str1: NSObject, str2: NSObject) -> Bool in
    return Int((str1 as! String))<Int((str2 as! String))

Okay, we've got a few problems here.

  1. str1 and str2 are declared as NSObject, when they are in fact Strings.

  2. Consequently, the as! String casts are unnecessary.

  3. Int(String) returns an Optional, so you need to take into account the case where the result may be nil. I'd just provide a default value; probably 0, although you could also use a guard statement to throw an error if you prefer.

In general, there's a lot of verbosity here. This whole closure can actually be succinctly written as a one-liner:

let sortedKeysArray = self.styles.keys.sorted { (Int($0) ?? 0) < (Int($1) ?? 0) }

Anyway, take care of these issues, and your code will compile.

Upvotes: 1

Alexander
Alexander

Reputation: 63331

That all seems pretty complex. You can simplify this quite a bit:

self.styles = [String: [Int: Int]]()

self.stylesLevel1Keys= self.styles.keys.sorted { Int($0)! < Int($1)! }

self.styleThemesPickerView.reloadAllComponents()

Upvotes: 0

Related Questions