Два серверных запроса завершены перед перезагрузкой табличного представления

У меня есть эти 2 запроса, которые я хочу выполнить перед перезагрузкой табличного представления (табличное представление зависит от них обоих).

Я пытался, как показано ниже, но это не работает.

Запрос 1 завершается, затем табличное представление перезагружается до того, как все будет сделано в запросе 2.

DispatchQueue.global(qos: DispatchQoS.QoSClass.default).async {
        //1. request 1:
        self.serverRequestAuth("/request1")
        //2. request 2:
        self.serverRequestAuth("/request2")
            DispatchQueue.main.async{
                //3. reload the table view
                self.tableView.reloadData()
            }
    }

Как мне поступить?

Упоминание: serverRequestAuth содержит запрос к серверу, разбор json, разбор словаря внутри него.

Метод serverRequestAuth:

func serverRequestAuth(_ requestName: String){
    let requestNameEscaped = requestName.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)!


    var request = NSMutableURLRequest()
    request = NSMutableURLRequest(url: URL(string: "\(self.view.getServerPath())\(requestNameEscaped)")!, cachePolicy: NSURLRequest.CachePolicy.reloadIgnoringLocalCacheData, timeoutInterval: 5)

    request.httpMethod = "GET"
    request.setValue(self.view.getAuth(), forHTTPHeaderField: "Authorization")
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")

    let task = URLSession.shared.dataTask(with: request as URLRequest) {data, response, err in
        if data != nil {
            if let dictionary = self.parseJSONData(data!) {
                self.parseDictionary(dictionary, typeOfRequest: requestName)
            }
        }
    }
    task.resume()
}

3 ответа

Решение

Попробуйте использовать DispatchSemaphore

func serverRequestAuth(_ requestName: String){
    let requestNameEscaped = requestName.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)!

    let semaphore = DispatchSemaphore(value: 0);
    var request = NSMutableURLRequest()
    request = NSMutableURLRequest(url: URL(string: "\(self.view.getServerPath())\(requestNameEscaped)")!, cachePolicy: NSURLRequest.CachePolicy.reloadIgnoringLocalCacheData, timeoutInterval: 5)

    request.httpMethod = "GET"
    request.setValue(self.view.getAuth(), forHTTPHeaderField: "Authorization")
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")

    let task = URLSession.shared.dataTask(with: request as URLRequest) {data, response, err in
        if data != nil {
            if let dictionary = self.parseJSONData(data!) {
                self.parseDictionary(dictionary, typeOfRequest: requestName)
                semaphore.signal();
            }
        }
    }
    task.resume()
    semaphore.wait(timeout: .distantFuture)
}

Попробуй это:

func serverRequestAuth(_ requestName: String, control:@escaping (_ check : Bool)-> Void){
    let requestNameEscaped = requestName.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)!


    var request = NSMutableURLRequest()
    request = NSMutableURLRequest(url: URL(string: "\(self.view.getServerPath())\(requestNameEscaped)")!, cachePolicy: NSURLRequest.CachePolicy.reloadIgnoringLocalCacheData, timeoutInterval: 5)

    request.httpMethod = "GET"
    request.setValue(self.view.getAuth(), forHTTPHeaderField: "Authorization")
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")

    let task = URLSession.shared.dataTask(with: request as URLRequest) {data, response, err in
        if data != nil {
            if let dictionary = self.parseJSONData(data!) {
                self.parseDictionary(dictionary, typeOfRequest: requestName)
                control(true)
            }else{

                control(false)
            }
        }
    }
    task.resume()
}

И Вы можете назвать это с:

serverRequestAuth("myStringRequest1", control: {(check)in

        if check  {
            self.serverRequestAuth("myStringRequest2", control: {(check) in

                if check {

                    self.tableView.reloadData()

                }else{

                    print("error Request 2")
                }
            })


        }else {

            print("error request 1")

        }
    })

У меня когда-то была похожая проблема. Чтобы предоставить простое решение, я написал эту маленькую библиотеку:

https://github.com/prine/ROConcurrency

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

var taskRequest1 = TaskComplex { (finished) -> () in
    self.serverRequestAuth("/request1", finished)
}

var taskRequest2 = TaskComplex { (finished) -> () in
    self.serverRequestAuth("/request2", finished)
}

var reloadTable = TaskComplex { (finished) -> () in
    DispatchQueue.main.async{
         // 3. reload the table view
         self.tableView.reloadData()
         finished()
    }
}

var barrierComplex = BarrierComplex(tasks: [taskRequest1, taskRequest2], afterTask: reloadTable)
barrierComplex.startTasks()

Ваш метод serverRequestAuth должен сообщить, когда он завершился асинхронно, поэтому вам нужно добавить завершенный обратный вызов:

func serverRequestAuth(_ requestName: String, _ finished:(Bool) -> ()) {
    let requestNameEscaped = requestName.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)!


    var request = NSMutableURLRequest()
    request = NSMutableURLRequest(url: URL(string: "\(self.view.getServerPath())\(requestNameEscaped)")!, cachePolicy: NSURLRequest.CachePolicy.reloadIgnoringLocalCacheData, timeoutInterval: 5)

    request.httpMethod = "GET"
    request.setValue(self.view.getAuth(), forHTTPHeaderField: "Authorization")
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")

    let task = URLSession.shared.dataTask(with: request as URLRequest) {data, response, err in
        if data != nil {
            if let dictionary = self.parseJSONData(data!) {
                self.parseDictionary(dictionary, typeOfRequest: requestName)

                // Here you call finished to tell the Barrier that its finished
                finished()
            }
        }
    }
    task.resume()
}
Другие вопросы по тегам