samuelmadethis
samuelmadethis

Reputation: 79

Type 'String' does not confirm to protocol 'NSCopying' with NSDictionary

I'm trying to use the Google Geolocation api, within Xcode using Swift, to allow the conversion of text address to latitude and longitude.

http://maps.googleapis.com/maps/api/geocode/json?address=washington%20dc is an example JSON call.

the error: Type 'String' does not confirm to protocol 'NSCopying', appears when trying to access elements within the dictionary of results.

@IBAction func submitButtonPressed(sender: AnyObject) {
    var address = addAddressTextField.text
    var escapedAddress = address.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
    let urlpath = "http://maps.googleapis.com/maps/api/geocode/json?address=" + escapedAddress!
    println(urlpath)

    let url = NSURL(string: urlpath)!


    let urlSession = NSURLSession.sharedSession()

    let jsonQuery = urlSession.dataTaskWithURL(url, completionHandler: { (data, responce, error) -> Void in

        if error != nil{
            println("there is an error")
        }

        var err : NSError?

        var results = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as NSDictionary

        if err != nil{
            println("there is a second error")
        }

        let formattedAddress: AnyObject! = results["results"]![0]!["formatted_address"]!
        let latitude: AnyObject! = results["results"]![0]!["geometry"]!["location"]!["lat"]!
        let longitude: AnyObject! = results["results"]![0]!["geometry"]!["location"]!["lng"]!

        dispatch_async(dispatch_get_main_queue(), { () -> Void in
            self.fullAddressLabel.text = "\(formattedAddress)"
            self.latLabel.text = "\(latitude)"
            self.longLabel.text = "\(longitude)"

        })

    })

    jsonQuery.resume()
}

The error only occurs on the lines:

let latitude: AnyObject! = results["results"]![0]!["geometry"]!["location"]!["lat"]!
let longitude: AnyObject! = results["results"]![0]!["geometry"]!["location"]!["lng"]!

and the let formattedAddress: AnyObject! = ... line works perfectly.

I have tried defining the variables as Strings and NSStrings and using '... as String' within the definition but to no luck.

Upvotes: 1

Views: 584

Answers (2)

nsij22
nsij22

Reputation: 879

I ran into the same issue with json try this

let latitude = results["results"]![0]!["geometry"]!!["location"]!!["lat"]!! as String
let longitude = results["results"]![0]!["geometry"]!!["location"]!!["lng"]!! as String

note, This does not include any error checking at all also if the labels you are updating are standard labels you can just do

mylabel.stringValue = latitude

or something like that :P

Here is a direct copy of how i phrase my json objects without error checking

var FilePath = object["main"]![row]!["Paths:"]!!["FilePath:"]!! as String

Upvotes: 0

JeremyP
JeremyP

Reputation: 86651

The problem is not the returned variables but the keys. NSDictionary expects its keys to conform to NSCopying and presumably a Swift string literal does not.

I would try to figure out exactly which access is causing the issue by not trying to get the whole thing in one line (your program will crash btw if you get an unexpected response because you assume all the keys exist in all the dictionaries).

On the assumption that you know you have at least one result and you have put it in a variable called results0 (this comes from external data so you must check it), I'd do this

var latitude: Double?
var longitude: Double?
if let geometry = results0["geometry"] as? NSDictionary
{
    if let location = geometry["location"] as? NSDictionary
    {
        latitude = location["lat"] as? Double
        longitude = location["lon"] as? Double
    }
}

Either you will get the same error on one of the lines accessing the dictionaries or something else may go wrong. You might have to fiddle about with the casting too to get it right (I haven't even tried to compile the above code). But the point is that now the code is spread out over several lines, it should be much easier to isolate the error.

Upvotes: 0

Related Questions