2017-09-22 3 views
2

J'utilise un sémaphore Dispatch pour attendre que j'effectue une requête URL JSON et cette attente peut prendre un certain temps. Pour surmonter cette situation, j'ai décidé de faire une nouvelle vue et de le montrer comme pop-up pendant que la demande est faite. Pour que je le code ci-dessous:ViewController en tant que fenêtre contextuelle en attente de l'envoi Semaphore

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

Où showPopup fait:

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

Le problème qui est, la fonction showPopup n'est appelé après de demande est déjà fait et le pop-up la vue ne clignote que sur l'écran. Comment l'appeler avant la demande?

Répondre

1

Le problème est que wait va bloquer le thread principal jusqu'à ce que le sémaphore effectue le signal, en bloquant l'interface utilisateur (entre autres) dans le processus.

Je vous suggère d'éliminer complètement ce sémaphore. (En général, c'est une très mauvaise pratique.) Affichez simplement la fenêtre contextuelle avant de lancer votre requête asynchrone et supprimez-la dans le gestionnaire d'achèvement (en vous assurant de l'envoyer dans la file principale si votre gestionnaire d'achèvement ne fonctionne pas fil principal).

+0

Le problème pour supprimer le sémaphore est que j'effectue une segue juste après. Et si je supprime, le segue est exécuté sans que le 'self.objects = output' soit réglé, ce dont j'ai besoin, puisque je vais utiliser cette information dans l'autre contrôleur de vue – Skal

+0

Alors, supprimez le segue de la cellule, et au lieu d'avoir la segue entre les contrôleurs de vue. Ensuite, lorsque vous supprimez le popover dans le gestionnaire de complétion, vous pouvez également exécuter le segue par programmation. Mais si vous attendez dans la file d'attente principale que vous pouvez affecter le fonctionnement des tâches nécessitant la file d'attente principale, vous présentez des risques de blocage, et si cela est fait à un moment inopportun, le processus de surveillance iOS peut tuer votre application. En règle générale, vous ne voulez jamais bloquer le thread principal. – Rob

+0

Merci, cela a bien fonctionné! Maintenant, j'essaie de comprendre pourquoi certains de mes éléments dans la vue se voient disparaître – Skal