Skal Skal - 26 days ago 10
Swift Question

ViewController as Popup While Wait for Dispatch Semaphore

I am using a Dispatch Semaphore to wait while I make a URL JSON request, and this wait might take a while. To overcome this situation I decided to make a new view and show it as pop up while the request is being made. For that I used the code below:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.showPopUp()
let semaphore = DispatchSemaphore(value: 0)

self.api.requestMedicationsByReagent(method: 1, ean: "", hash: medHash!, gen: generic) { output in
semaphore.signal()
self.objects = output
}
// Thread will wait here until async task closure is complete
let _ = semaphore.wait(timeout: DispatchTime.distantFuture)
}


Where showPopUp does:

func showPopUp() {
let popOverVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "loadingPopUp") as! PopUpViewController

self.addChildViewController(popOverVC)
popOverVC.view.frame = self.view.frame
self.view.addSubview(popOverVC.view)
popOverVC.didMove(toParentViewController: self)
}


The problem with that is, the showPopUp function is only being called after de request is already made and the pop-up view just flashes on the screen. How do I call it before the request?

Rob Rob
Answer Source

The problem is that wait is going to block the main thread until the semaphore performs the signal, blocking the UI (amongst other things) in the process.

I'd suggest that you eliminate that semaphore entirely. (It's a really bad practice, in general, anyway.) Just show the popup before you initiate your asynchronous request and dismiss it in the completion handler (making sure to dispatch that to the main queue if your completion handler doesn't run on the main thread).