I am trying to us a RESTful API that returns some json data. I want to encapsulate the code that creates the HTTP Request and sets the headers in its own method so I can call it by entering a url String and then have the method return a JSON object.
In the following snippet of code, I have already created the request object and set the headers, and I call that variable "req". I have not declared any objects named data, response, or error. I have the following code that correctly prints out a JSON object
let sesh = NSURLSession.sharedSession() let dataTask = sesh.dataTaskWithRequest(req, completionHandler: {(data, response, error) in var jsonError : NSError? let jsonBlob = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableLeaves, error: &jsonError) println(jsonBlob) }); dataTask.resume()
So here's my question. How do I make it so that this completionHandler block is able to return the jsonBlob, which is of type "AnyObject!"? If I modify the code slightly to be the following:
let sesh = NSURLSession.sharedSession() let dataTask = sesh.dataTaskWithRequest(req, completionHandler: {(data, response, error) -> AnyObject! in var jsonError : NSError? let jsonBlob : AnyObject! = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableLeaves, error: &jsonError) return jsonBlob }); dataTask.resume()
then the program will not compile as the call to dataTaskWithRequest:completionHandler gives a compiler warning saying:
Could not find an overload for 'dataTaskWithRequest' that accepts the supplied arguments
I don't understand this. I'm using the correct syntax for returning closures, as is given in this page of the Swift Docs:
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html
Swift's closures can return values as well as take parameters, and you can use those closures in functions. Even better, those functions can also return values, but it's easy for your brain to get a bit fuzzy here because there's a lot of syntax.
Closures are represented by traits, which means you can't return closures directly.
As an example, many functions that start an asynchronous operation take a closure argument as a completion handler. The function returns after it starts the operation, but the closure isn't called until the operation is completed—the closure needs to escape, to be called later.
If we wanted to pass that closure into a function so it can be run inside that function, we would specify the parameter type as () -> Void . That means “accepts no parameters, and returns Void ” – Swift's way of saying “nothing”.
func getSomething(callback: (Array<AnyObject>) -> ()) { var dataTask = NSURLSessionDataTask() dataTask = session.dataTaskWithRequest(request) { (data, response, error) in if (error == nil) { var callbackArray = Array<MyObject>() let responseDict = NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers, error: nil) as NSDictionary let response = responseDict.objectForKey("response_key") as NSDictionary let array = response.objectForKey("array_key") as NSArray for item: AnyObject in array { var arrayItem = MyObject(dict: item as NSDictionary) callbackArray.append(arrayItem) } callback(callbackArray) } else { // handle an error } } dataTask.resume() }
Then you could do something like:
getSomething() { (response) in if let responseArray = response as? Array<MyObject> { self.somethings = responseArray } }
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