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