Closing returns a value (earlier completion of the lock)

I want to return some values โ€‹โ€‹after the completion of a long-term operation. But also, I would like to separate the logic and gui.

For example; I have two classes

  • SomeServices.swift, which has a method called getDataFromService ...
  • MyTableViewController.swift, which will display the result from "getDataFromService"

So, earlier in Objective-C, I just added a method to SomeServices, like this:

(void)getDataFromService:(void (^)(NSArray *, NSError *))completionBlock{ ...... } 

In this method, I just called completionBlock(myData, myError) to return my values โ€‹โ€‹to tableviewcontroller.

What will be the equivalent closure I have to define in SomeServices.swift and how will it be called in MyTableViewController?

I know how to cause simple closures like this:

  ....({ responseData, error in if(!error){ //Do something } }) 

But I have no idea how to define a closure with the equivalent of Block completion.

Any help would be appreciated

+8
ios8 swift
source share
3 answers

The plus of closing is that you can convey whatever you want. Methods or functions - it does not matter.

You can pass the function inside the parameters and just call it.

 func someFunctionThatTakesAClosure(completionClosure: () -> ()) { // function body goes here if(error = false) { completionClosure() } } //Call it someFunctionThatTakesAClosure({ //Completions Stuff println("someFunctionThatTakesAClosure") }); 

Excerpt from: Apple Inc. "Fast programming language." interactive books. https://itun.es/ch/jEUH0.l

+12
source share

The answer is given in the language manual:

Suppose you want to return a string. This is the syntax

 ({(responseData: DataClass, error: ErrorClass) -> String in //do stuff - calculations etc.. return calculatedString }) 

Here is an example that takes two strings and concatenates them, and returns the result:

 let sumStrings = ({(first: String, second: String) -> String in return first + " " + second }) 

then you can do the following:

 sumStrings("Hello","Swift") // "Hello Swift" 
+2
source share

This is how I use singleton ServiceManager to achieve this.

 class ServiceManager: NSObject { // Static Instance variable for Singleton static var sharedSessionManager = ServiceManager() // Function to execute GET request and pass data from escaping closure func executeGetRequest(with urlString: String, completion: @escaping (Data?) -> ()) { let url = URL.init(string: urlString) let urlRequest = URLRequest(url: url!) URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in // Log errors (if any) if error != nil { print(error.debugDescription) } else { // Passing the data from closure to the calling method completion(data) } }.resume() // Starting the dataTask } // Function to perform a task - Calls executeGetRequest(with urlString:) and receives data from the closure. func downloadMovies(from urlString: String, completion: @escaping ([Movie]) -> ()) { // Calling executeGetRequest(with:) executeGetRequest(with: urlString) { (data) in // Data received from closure do { // JSON parsing let responseDict = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String: Any] if let results = responseDict!["results"] as? [[String:Any]] { var movies = [Movie]() for obj in results { let movie = Movie(movieDict: obj) movies.append(movie) } // Passing parsed JSON data from closure to the calling method. completion(movies) } } catch { print("ERROR: could not retrieve response") } } } } 

The following is an example of using the singleton class.

 ServiceManager.sharedSessionManager.downloadMovies(from: urlBase) { (movies : [Movie]) in // Object received from closure self.movies = movies DispatchQueue.main.async { // Updating UI on main queue self.movieCollectionView.reloadData() } } 

Hope this helps anyone looking for the same solution.

+1
source share

All Articles