I would like to create a function in Swift 2 that gets data from a URL and returns it as a JSON object using NSURLSession. At first, this seemed pretty straight forward. I wrote the following:
func getJson(url:NSURL, completeWith: (AnyObject?,NSURLResponse?,NSError?)->Void) -> NSURLSessionTask? {
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url) {
(data:NSData?, response:NSURLResponse?, error:NSError?) -> Void in
if error != nil {
completeWith(nil, response, error)
}
if let data = data {
do {
let object:AnyObject? = try NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments)
} catch let caught as NSError {
completeWith(nil, response, caught)
}
completeWith(object, response, nil)
} else {
completeWith(nil, response, error)
}
}
return task
}
However, that doesn't compile because the completion block doesn't declare "throws". The exact error is Cannot invoke 'dataTaskWithURL' with an argument list of type '(NSURL, (NSData?, NSURLResponse?, NSError?) throws -> Void)'
. Even though I'm catching all errors in my do/catch
statement, Swift still wants to propagate the NSError up the chain. The only way I can see around it is to use try!
, like this:
if let data = data {
let object:AnyObject? = try! NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments)
completeWith(object, response, nil)
} else {
completeWith(nil, response, error)
}
Now everything compiles just fine, but I've lost the NSError that's thrown by NSJSONSerialization.JSONObjectWithData
.
Is there was I can capture the NSError potentially thrown by NSJSONSerialization.JSONObjectWithData
and propagate it to the completion block without modifying the completion block's signature?
Follow the steps given in the previous chapter to install Alamofire in the application and open the xcworkspace file. Create a MainViewController class and make a get request to print the API data using Alamofire. // Do any additional setup after loading the view. print("Response.
An object that converts between JSON and the equivalent Foundation objects.
Swift JSON Parsing JSON stands for JavaScript Object Notation. It's a popular text-based data format used everywhere for representing structured data. Almost every programming language supports it with Swift being no exception. You are going to use JSON a lot throughout your career, so make sure you don't miss out.
I think, your catch is not exhaustive, so you need something like this:
do
{
let object:AnyObject? = try NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments)
completeWith(object, response, nil)
} catch let caught as NSError {
completeWith(nil, response, caught)
} catch {
// Something else happened.
// Insert your domain, code, etc. when constructing the error.
let error: NSError = NSError(domain: "<Your domain>", code: 1, userInfo: nil)
completeWith(nil, nil, error)
}
to address the question from Jguffey. I saw the same error when I tried calling the function like this:
let taskResult = getJson(url!) {
(any: AnyObject,resp: NSURLResponse,error: NSError) in
it should be like this:
let taskResult = getJson(url!) {
(any: AnyObject?,resp: NSURLResponse?,error: NSError?) in
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With