Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling Flickr API with Swift

I was trying to get some JSON data from a Flickr API but my Swift code is not working.
This is based on Jameson Quave's tutorial on making an API request with Swift

func GetFlickrData(tags: String) {

    let baseURL = "https://api.flickr.com/services/rest/?&method=flickr.photos.search"
    let apiString = "&api_key=\(apiKey)"
    let searchString = "&tags=\(tags)"

    let requestURL = NSURL(string: baseURL + apiString + searchString)   
    let session = NSURLSession.sharedSession()

    let task = session.dataTaskWithURL(requestURL, completionHandler: { data, response, error -> Void in

        var result = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: nil) as NSDictionary

        dispatch_async(dispatch_get_main_queue(), {
            println(result)
        })
    })

    task.resume()
}

This shows me an error for the requestURL argument that says: "Vaue of type NSURL? not unwrapped". When I add "!", the error goes away. But, I still get a runtime error when making the call.

In the debugger, I see:

data = (NSData!)16642 bytes
fatal error: unexpectedly found nil while unwrapping an Optional value

What am I missing?

EDIT - This was working fine on Xcode 6, it broke when updating Xcode to version 6.1

like image 694
nv.snow Avatar asked Oct 21 '14 20:10

nv.snow


1 Answers

The result variable actually is of type NSDictionary? and will raise a runtime error if it is nil and you try to access it. The JSONObjectWithData function returns an optional as you can see in it's declaration:

class func JSONObjectWithData(data: NSData, options opt: NSJSONReadingOptions, error: NSErrorPointer) -> AnyObject?

You have to cast the result in an object of type NSDictionary? and not NSDictionary in order to make it work

let result = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: nil) as NSDictionary?
if let unwrappedResult = result {
    println(unwrappedResult)
}

UPDATE FOR SWIFT 2:

JSONObjectWithData no longer returns an Optional but instead makes use of the new error handling and is marked as throwing. The signature now looks like this:

public class func JSONObjectWithData(data: NSData, options opt: NSJSONReadingOptions) throws -> AnyObject

To achieve the same one would now have to wrap the call inside a do/catch block or alternatively use try? instead of try:

do {
    let result = try NSJSONSerialization.JSONObjectWithData(data, options: []) as? NSDictionary
    print(result)
} catch {
    print(error)
}
like image 137
Daehn Avatar answered Sep 30 '22 03:09

Daehn