3

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?

Skalwalker
  • 299
  • 3
  • 23

1 Answers1

2

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).

Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • The problem removing the semaphore is that I perform a segue right after it. And if I do remove, the segue is executed without the `self.objects = output` being set, which I need it to be, since I will use this information in the other view controller – Skalwalker Sep 22 '17 at 22:01
  • So remove the segue from the cell, and instead have the segue between the view controllers. Then, when you remove the popover in the completion handler, you can programmatically perform the segue, too. But if you wait on the main queue you can affect operation of tasks that require the main queue, you introduce deadlock risks, and if this is done at an inopportune time, the iOS watchdog process can kill your app. As a rule, you never want to block the main thread. – Rob Sep 22 '17 at 22:18
  • Thanks, this worked fine! Now I am trying to figure out why some of my elements in the view being segued disappears – Skalwalker Sep 23 '17 at 01:33