Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wait until an asynchronous api call is completed - Swift/IOS

Tags:

closures

swift

I'm working on an ios app where in my appDelegate I have:

func application(application: UIApplication!, didFinishLaunchingWithOptions launchOptions: NSDictionary!) -> Bool {    
    self.api.signInWithToken(emailstring, token: authtokenstring) {
        (object: AnyObject?, error:String?) in            
            if(object != nil){
                self.user = object as? User
                // go straight to the home view if auth succeeded
                var rootViewController = self.window!.rootViewController as UINavigationController
                let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
                var homeViewController = mainStoryboard.instantiateViewControllerWithIdentifier("HomeViewController") as HomeViewControllerenter
                // code here
                rootViewController.pushViewController(homeViewController, animated: true)
            }
        }
    return true
}

The api.signInWithToken is an asynchronous call made with Alamofire, and I would like to wait for it's completion before returning true at the end end of func application.

like image 972
brian S Avatar asked Nov 06 '14 20:11

brian S


2 Answers

Note: You should not do it this way, as it blocks the thread. See Nate's comment above for a better way.

There is a way to wait for an async call to complete using GCD. The code would look like the following

var semaphore = dispatch_semaphore_create(0)

performSomeAsyncTask {
    ...
    dispatch_semaphore_signal(semaphore)
}

dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
dispatch_release(semaphore)

Wikipedia has an OK article in case you know nothing about semaphores.

like image 180
Anton Avatar answered Sep 24 '22 01:09

Anton


This is the solution in Swift 3. Again this blocks the thread until asynchronous task is complete, so it should be considered only in specific cases.

let semaphore = DispatchSemaphore(value: 0)

performAsyncTask {
    semaphore.signal()
}

// Thread will wait here until async task closure is complete   
semaphore.wait(timeout: DispatchTime.distantFuture)
like image 21
Legoless Avatar answered Sep 26 '22 01:09

Legoless