In Java, CountDownLatch is a class in the JDK that is often used together with asynchronous tasks, and in tests.
An example use case is when you need two HTTP requests to complete before going to the next step, like in a login form where two HTTP requests must complete before the user can start using the app.
Here is how I did it in Swift 3 on iOS
import Foundation final class CountDownLock { private var remainingJobs: Int32 private let isDownloading = DispatchSemaphore(value: 0) // initially locked init(count: Int32) { remainingJobs = count } func countDown() { OSAtomicDecrement32(&remainingJobs) if (remainingJobs == 0) { self.isDownloading.signal() // unlock } } func waitUntilZero() { self.isDownloading.wait(timeout: DispatchTime.distantFuture) } }
An example of use, with the non-essential parts left out
class LoginViewController: UIViewController { @IBOutlet weak var loginButton: UIButton? private let counter = CountDownLock(count: 2) private func downloadCertificate() { self.doDownLoadCertificate({ (success, errorMessage, errorDetailObject) -> Void in if (success) { self.counter.countDown() } else { self.reportErrorToUser(errorMessage, detail: errorDetailObject) } }) } private func login(username:String, password:String) { self.loginToPortal(username, password:String, onCompletion: { (success, errorMessage, errorDetailObject) -> Void in if (success) { self.counter.countDown() } else { self.reportErrorToUser(errorMessage, detail: errorDetailObject) } })) } override func viewDidLoad() { self.downloadCertificate(); super.viewDidLoad() } @IBAction func loginButtonWasClicked(sender: UIButton) { print("Button was clicked") login(username, password) // Wait until all background jobs are done self.counter.waitForZero() // non-busy wait, UI is not blocked } }