amir-f
amir-f

Reputation: 731

Why do I get this error in Swift "Could not find member subscript"

I'm trying to work with the dictionary object result returned after a facebook login. The result variable looks like this

 result = [ location: ["name": "Paris, France", "id": "34534999333"]  ] 

and my goal is to access the location name. I try this code:

 if let location = result["location"]?["name"] as? String {
              //do something      
      }

but I get the error "could not find member subscript." I see nothing wrong with the logic of my code. If result["location"] exists, then look for the index "name" in it, cast it as a string, and if successful, set the constant "location" equal to it.

I could do what I want with a longer code but I just want to learn why Swift doesn't understand the code above.

Upvotes: 1

Views: 235

Answers (3)

Tommie C.
Tommie C.

Reputation: 13181

The compiler was confused. The reasoning is that the "location:" in the original looks like a dictionary assignment but the key location also looks like a variable as written. Surrounding that value with quotes to make it a distinct dictionary key will produce the desired Dictionary object. You can unwrap the place information using the following syntax.

//: Playground - noun: a place where people can play

import UIKit

let result = [  "location": ["name": "Paris, France", "id": "34534999333"]  ]

if let place = result["location"]?["name"]   {
    //do something
    print(place)

}

Option-clicking on any suspect variables after you've written the line of code would normally show a result type of << error type >> whenever the compiler is having an issue.

Upvotes: 0

vacawama
vacawama

Reputation: 154731

I suspect your problem is that result is an optional type. option-click on the result variable. If it is of type NSDictionary? or something like [NSObject: AnyObject]? then result will have to be unwrapped before you can use it. I would first try:

if let location = result?["location"]?["name"] as? String {
    //do something      
}

If result is AnyObject or AnyObject?, I would suggest taking this a step at a time:

if let dict = result as? NSDictionary {
    if let location = dict["location"] as? NSDictionary {
        if let name = location["name"] as? String {
            // use name
        }
    }
}

You can compact the above into a single if:

if let name = ((result as? NSDictionary)?["location"] as? NSDictionary)?["name"] as? String {
    // use name
}

Upvotes: 1

Stuart
Stuart

Reputation: 37053

Apart from the apparent typo (the 'location' in the assignment to result should surely be a string literal "location"?), the optional downcast to String in the if let statement is unnecessary. Swift has already inferred the type - it knows that result["location"]?["name"] returns the type String?.

as? String should be producing a compiler warning, but I would not expect it to be "could not find member subscript" unless the compiler has got quite confused (which has been know at this relatively early stage in Swift's development!). Start by removing the downcast.

Upvotes: 0

Related Questions