Search code examples
iosswiftflickr

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


Solution

  • 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)
    }