Dans mon application, j'ai une fonction qui crée une NSRURLSession et envoie une NSURLRequest en utilisant
sesh.dataTaskWithRequest(req, completionHandler: {(data, response, error)
Dans le bloc d'achèvement de cette tâche, je dois faire un calcul qui ajoute une UIImage au viewcontroller appelant. J'ai un func appelé
func displayQRCode(receiveAddr, withAmountInBTC:amountBTC)
qui effectue le calcul d'ajout d'UIImage. Si j'essaie d'exécuter le code d'ajout de vue à l'intérieur du bloc de complétion, Xcode génère une erreur indiquant que je ne peux pas utiliser le moteur de mise en page pendant un processus en arrière-plan. J'ai donc trouvé du code sur SO qui tente de mettre en file d'attente une méthode sur le thread principal:
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(0.0 * Double(NSEC_PER_MSEC)))
dispatch_after(time, dispatch_get_main_queue(), {
let returned = UIApplication.sharedApplication().sendAction("displayQRCode:", to: self.delegate, from: self, forEvent: nil)
})
Cependant, je ne sais pas comment ajouter les paramètres "receiveAddr" et "amountBTC" à cet appel de fonction. Comment faire cela, ou quelqu'un peut-il suggérer un moyen optimal d'ajouter un appel de méthode à la file d'attente principale de l'application?
Version Swift 3+ et Swift 4:
DispatchQueue.main.async { print("Hello") }
Swift 3 et Xcode 9.2:
dispatch_async_on_main_queue { print("Hello") }
la source
Swift 2
En utilisant les fermetures de fuite, cela devient:
dispatch_async(dispatch_get_main_queue()) { self.tableView.reloadData() }
Trailing Closures est un sucre syntaxique Swift qui permet de définir la fermeture en dehors de la portée du paramètre de fonction. Pour plus d'informations, consultez Fermetures de fin dans le Guide du langage de programmation Swift 2.2.
Dans le cas de dispatch_async, l'API est
func dispatch_async(queue: dispatch_queue_t, _ block: dispatch_block_t)
depuisdispatch_block_t
un alias de type pour() -> Void
- Une fermeture qui reçoit 0 paramètre et n'a pas de valeur de retour, et le bloc étant le dernier paramètre de la fonction, nous pouvons définir la fermeture dans la portée externe dedispatch_async
.la source
Recharger la collectionAfficher sur le fil principal
DispatchQueue.main.async { self.collectionView.reloadData() }
la source
Voici la meilleure syntaxe de style Swifty / Cocoa (IMO) pour obtenir le même résultat que les autres réponses:
NSOperationQueue.mainQueue().addOperationWithBlock({ // Your code here })
Ou vous pouvez récupérer la bibliothèque Async Swift populaire pour encore moins de code et plus de fonctionnalités:
Async.main { // Your code here }
la source
OperationQueue.main.addOperation({ }
La bonne façon de faire est d'utiliser dispatch_async dans la main_queue, comme je l'ai fait dans le code suivant
dispatch_async(dispatch_get_main_queue(), { (self.delegate as TBGQRCodeViewController).displayQRCode(receiveAddr, withAmountInBTC:amountBTC) })
la source
Voici une jolie petite fonction globale que vous pouvez ajouter pour une syntaxe plus agréable:
func dispatch_on_main(block: dispatch_block_t) { dispatch_async(dispatch_get_main_queue(), block) }
Et utilisation
dispatch_on_main { // Do some UI stuff }
la source
//Perform some task and update UI immediately. DispatchQueue.global(qos: .userInitiated).async { // Call your function here DispatchQueue.main.async { // Update UI self.tableView.reloadData() } } //To call or execute function after some time DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) { //Here call your function } //If you want to do changes in UI use this DispatchQueue.main.async(execute: { //Update UI self.tableView.reloadData() })
la source
N'oubliez pas de vous affaiblir si vous vous utilisez à l'intérieur de la fermeture.
dispatch_async(dispatch_get_main_queue(),{ [weak self] () -> () in if let strongSelf = self { self?.doSomething() } })
la source