Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use completionHandler Closure with return in Swift?

Tags:

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

like image 793
almel Avatar asked Jul 09 '14 07:07

almel


People also ask

Can closure return value Swift?

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.

Can you return from a closure?

Closures are represented by traits, which means you can't return closures directly.

What is difference between closure and completion handler Swift?

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.

How do you pass closure in Swift?

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”.


1 Answers

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     } } 
like image 135
fulvio Avatar answered Nov 07 '22 05:11

fulvio