How to wait for a function to complete on iOS / Swift before launching the second

I basically have methods that are called in my DidLoad view. The first gets custom search settings and saves the variable preferences at the top. After that I want to access and work with these variables in the second function. But now the variables are always zero when I want to access them in the second function.

How can I configure my viewDidLoad so that the second function is executed only once and my data request is successfully completed?

var searchLocation = String() var searchLocationCoordinates = [String:Double]() var searchRange = Int() override func viewDidLoad() { super.viewDidLoad() // Gets the user search preference getTheSearchLocationAndRange() // Loads the data from the database loadDataFromDatabase() } 

So far I have read stuff with dispatch_asynch dispatcher or completion handler. Maybe someone can post some code that I can use in my DidLoad view and make it work?

+6
source share
3 answers

Ok, I found a solution. I basically called the function at the end of the first.

So basically:

  var searchLocation = String() var searchLocationCoordinates = [String:Double]() var searchRange = Int() override func viewDidLoad() { super.viewDidLoad() // Gets the user search preference getTheSearchLocationAndRange() } func getTheSearchLocationAndRange() { // Code for getTheSearchLocationAndRange() loadDataFromDatabase() } func loadDataFromDatabase(){ // Code for loadDataFromDatabase() } 
+1
source

You can use Swift closure! They are made for this.

Refer to the Apple manual: Closures

Here is the code you need in your specific case.

FinishedDownload is a close. When getTheSearchLocationAndRange() is called, its code is executed until the completed() , which waits for the completion of all the processes of the function. After the processes (for example, loading) are completed() causes a closure that activates the code defined in getTheSearchLocationAndRange { () -> () in . Therefore, loadDataFromDatabase() is called only once when getTheSearchLocationAndRange() completely completed execution, and the data is present (not zero).

  var searchLocation = String() var searchLocationCoordinates = [String:Double]() var searchRange = Int() typealias FinishedDownload = () -> () override func viewDidLoad() { super.viewDidLoad() getTheSearchLocationAndRange() } func getTheSearchLocationAndRange(completed: FinishedDownload) { // Code for searching Location Range HERE completed() } getTheSearchLocationAndRange { () -> () in loadDataFromDatabase() } 

I hope this solves your problem and answers your question :)

By the way, about β€œleaving your hanging GUI” part, Alamofire automatically takes care of this for you. If you are not using Alamofire, you will have to manually assign an asynchronous request to the background thread so that your GUI does not stop responding.

+6
source

I wrote a demo project and posted it on GitHub, which simulates asynchronous network boot processing. Take a look at the DuncanMC / SwiftCompletionHandlers .

In particular, look at the asyncFetchImage () method, which describes this thread almost exactly: Uses the asynchronous method inside itself and takes the completion block, which it calls as soon as the asynchronous load is executed.

This is a generic template that you should use. Write a method that accepts block / close completion. Internally, this method is called by any asynchronous function that it needs, and then causes the completion of closure from the closure of the closure of the asynchronous method.

The asyncFetchImage function is as follows:

 func asyncFetchImage(imageName imageName: String, completion: ( image: UIImage?, status: String) -> ()) { print("Entering \(#function)") //Simulate a network operation by waiting a few seconds before loading an image let nSecDispatchTime = dispatch_time(DISPATCH_TIME_NOW, Int64(3.0 * Double(NSEC_PER_SEC))) let queue = dispatch_get_main_queue() dispatch_after(nSecDispatchTime, queue) { () -> Void in let result = UIImage(named: imageName) print("Loading image in background") let status = result != nil ? "image loaded" : "Error loading image" print("About to call completion handler") completion(image: result, status: status) } print("Leaving \(#function)") } 
+3
source

All Articles