web-dev-qa-db-fra.com

Comment faire deux appels simultanés d'API dans Swift 4

Merci d'avance pour l'aide, j'ai deux appels API, les deux sont simultanés et tout appel pourrait être un succès en premier (je ne veux pas d'appel en séquence), après le succès des deux appels, je dois arrêter mon indicateur d'activité et recharger ma table , Voici mon code mais je ne sais pas si c'est la bonne façon ou non et comment recharger ma tableView et arrêter mon indicateur d'activité.

func downloadDetails(){
    let operationQueue: OperationQueue = OperationQueue()
    let operation1 = BlockOperation() {
    WebServiceManager.getAData(format:A, withCompletion: {(data: Any? , error: Error?) -> Void in

          if let success = data {
              DispatchQueue.main.async {
                  (success code)
              }
           }
        })

        let operation2 = BlockOperation() {
        webServiceManager.getBData(format: B, withCompletion: {(data: Any? , error: Error?) -> Void in

                if let success = data {
                    DispatchQueue.main.async {
                       (success code)
                    }
                }
            })
        }
        operationQueue.addOperation(operation2)
    }
    operationQueue.addOperation(operation1)
}
downloadDetails() "calling function"
9
King

C'est exactement le cas d'utilisation de DispatchGroup. Entrez dans le groupe pour chaque appel, quittez le groupe une fois l'appel terminé et ajoutez un gestionnaire de notifications pour qu'il se déclenche lorsque tout est terminé. Il n'est pas nécessaire d'avoir une file d'attente d'opérations distincte; ce sont déjà des opérations asynchrones.

func downloadDetails(){
    let dispatchGroup = DispatchGroup()

    dispatchGroup.enter()   // <<---
    WebServiceManager.getAData(format:A, withCompletion: {(data: Any? , error: Error?) -> Void in

        if let success = data {

            DispatchQueue.main.async {
                (success code)
                dispatchGroup.leave()   // <<----
            }
        }
    })

    dispatchGroup.enter()   // <<---
    webServiceManager.getBData(format: B, withCompletion: {(data: Any? , error: Error?) -> Void in

        if let success = data {

            DispatchQueue.main.async {
               (success code)
               dispatchGroup.leave()   // <<----
            }
        }
    })

    dispatchGroup.notify(queue: .main) {
        // whatever you want to do when both are done
    }
}
9
Rob Napier

Que diriez-vous d'avoir 2 variables booléennes, une pour chaque requête. Le code de réussite du premier est défini sur l'une des variables et l'autre code de réussite sur la seconde.

La fonction de vérification doit vérifier que les deux variables sont vraies avant d'arrêter l'indicateur d'activité et d'actualiser la vue de table.

var success1 = false
var success2 = false

//For the first api call
DispatchQueue.main.async {
    success1 = true
    successCode()
}

//For the second api call
DispatchQueue.main.async {
    success2 = true
    successCode()
}

func successCode() {
    if ((success1 == true) && (success2 == true)) {
        activityIndicator.stopAnimating()
        tableView.reloadData()
    }
}
0
JoeGalind

J'utiliserais OperationQueue.

Il est préférable pour les tâches de longue durée et vous donne le contrôle pour annuler la demande, si nécessaire.

À la fin de chaque opération, vous pouvez vérifier le nombre d'opérations pour connaître les opérations restantes.

J'ai ajouté un pseudo code.

let operationQueue: OperationQueue = OperationQueue()

func downloadDetails(){

    let operation1 = BlockOperation() { [weak self] in

        guard let strongSelf = self else {
            return
        }

        sleep(2)

        DispatchQueue.main.async {
            strongSelf.handleResponse()
        }

        let operation2 = BlockOperation() { [weak self] in

            guard let strongSelf = self else {
                return
            }

            sleep(2)

            DispatchQueue.main.async {
                strongSelf.handleResponse()
            }
        }
        strongSelf.operationQueue.addOperation(operation2)
    }

    self.operationQueue.addOperation(operation1)
}

func handleResponse() {
    print("OPERATIONS IN PROGRESS: \(self.operationQueue.operations.count)")
    if self.operationQueue.operations.count == 0 {
        print("ALL OPERATIONS ARE COMPLETE")
    }
}

func cancelOperation() {
    self.operationQueue.cancelAllOperations()
}

Cela imprime

OPERATIONS IN PROGRESS: 1
OPERATIONS IN PROGRESS: 0
ALL OPERATIONS ARE COMPLETE
0
kthorat