web-dev-qa-db-fra.com

Dans Swift comment appeler une méthode avec des paramètres sur le thread principal de GCD?

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?

177
almel

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

459
codester

Swift 3 & Swift 4 version:

DispatchQueue.main.async {
    print("Hello")
}

Swift3 et XCode 9.2:

dispatch_async_on_main_queue {
     //Your code
     print("Hello")
 }
79
DazChong

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.

14
Maxim Veksler

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
}
6
pejalo

Recharger la collection Afficher sur le fil principal

 DispatchQueue.main.async {
      self.collectionView.reloadData()
 }
6
Sanjay Mali

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

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
}
2
Mateusz Grzegorzek
//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()
})
1
iOS

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()
            }
        })
1
villy393