Как сделать два одновременных вызова API в Swift 4 - PullRequest
0 голосов
/ 28 мая 2018

Заранее спасибо за помощь, у меня есть два вызова API, оба являются одновременными, и любой вызов может сначала быть успешным (я не хочу последовательный вызов), после успеха обоих вызовов мне нужно остановить индикатор активности иперезагрузите мой tableView, вот мой код, но я не знаю, это правильный путь или нет, и как перезагрузить мой tableView и остановить индикатор активности.

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"

Ответы [ 3 ]

0 голосов
/ 28 мая 2018

Это именно тот случай использования DispatchGroup.Введите группу для каждого вызова, выйдите из группы, когда вызов завершится, и добавьте обработчик уведомлений, чтобы он срабатывал, когда все они сделаны.Нет необходимости в отдельной очереди операций;это уже асинхронные операции.

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
    }
}
0 голосов
/ 28 мая 2018

Я бы использовал OperationQueue.

Это предпочтительно для длительной задачи и дает вам возможность отменить запрос, если это необходимо.

В конце каждой операции вы можете проверить количество операций, чтобы узнать оставшиеся операции.

Я добавил псевдокод.

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

Это печатает

OPERATIONS IN PROGRESS: 1
OPERATIONS IN PROGRESS: 0
ALL OPERATIONS ARE COMPLETE
0 голосов
/ 28 мая 2018

Как насчет двух логических переменных, по одной для каждого запроса.Код успешного завершения для первого устанавливает значение true для одной из переменных, а для другого кода успеха - для второго.

Функция проверки должна проверять, что обе переменные имеют значение true, прежде чем останавливать индикатор активности и обновлять представление таблицы.

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