Dans mon application, j'ai une fonction qui crée une NSRURLSession et envoie un NSURLRequest en utilisant
sesh.dataTaskWithRequest(req, completionHandler: {(data, response, error)
Dans le bloc d'achèvement de cette tâche, je dois effectuer un calcul qui ajoute un UIImage au viewcontroller appelant. J'ai un func appelé
func displayQRCode(receiveAddr, withAmountInBTC:amountBTC)
cela fait le calcul en ajoutant UIImage. Si j'essaie d'exécuter le code d'ajout de vues à l'intérieur du bloc d'achèvement, Xcode génère une erreur indiquant que je ne peux pas utiliser le moteur de présentation pendant un processus en arrière-plan. J'ai donc trouvé du code sur SO qui tente de mettre une méthode en file d'attente 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 puis-je 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?
Il suffit d'écrire ceci dans completion handler
. Pas besoin d'utiliser dispatch_after
dispatch_async(dispatch_get_main_queue(), {
let delegateObj = UIApplication.sharedApplication().delegate as YourAppDelegateClass
delegateObj.addUIImage("yourstring")
})
Swift 3/4:
DispatchQueue.main.async {
let delegateObj = UIApplication.sharedApplication().delegate as YourAppDelegateClass
delegateObj.addUIImage("yourstring")
}
Aussi pour envoi après dans la file principale
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
// your code here
}
Remplacez YourAppDelegateClass
par votre classe déléguée
Swift 3 & Swift 4 version:
DispatchQueue.main.async {
print("Hello")
}
Swift3 et XCode 9.2:
dispatch_async_on_main_queue {
//Your code
print("Hello")
}
Swift 2
En utilisant les fermetures de fin, cela devient:
dispatch_async(dispatch_get_main_queue()) {
self.tableView.reloadData()
}
Trailing Closures est le sucre syntaxique Swift qui permet de définir la fermeture en dehors du champ d'application du paramètre de fonction. Pour plus d'informations, voir Trailing Closures in Swift 2.2 Guide du langage de programmation.
Dans le cas de dispatch_async, l'API est func dispatch_async(queue: dispatch_queue_t, _ block: dispatch_block_t)
puisque dispatch_block_t
est un alias de type pour () -> Void
- Une fermeture qui reçoit 0 paramètre et n'a pas de valeur de retour, et block est le dernier paramètre de la fonction. nous pouvons définir la fermeture dans la portée externe de dispatch_async
.
Voici la syntaxe de style Swifty/Cocoa la plus agréable (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 populaire Async Swift pour encore moins de code et plus de fonctionnalités:
Async.main {
// Your code here
}
Recharger la collection Afficher sur le fil principal
DispatchQueue.main.async {
self.collectionView.reloadData()
}
Pour ce faire, utilisez dispatch_async dans la file d'attente principale, comme je l'ai fait dans le code suivant.
dispatch_async(dispatch_get_main_queue(), {
(self.delegate as TBGQRCodeViewController).displayQRCode(receiveAddr, withAmountInBTC:amountBTC)
})
Voici une petite fonction globale intéressante 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
}
//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()
})
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()
}
})