Как дождаться полной загрузки данных


#1

Есть класс в котором описываются статичные методы, которые вызываются из разных вью контроллеров и запрашивают данные с интернета. Размер этих данных заранее неизвестен. Как заставить метод дожидаться полной загрузки данных?
В качестве костыля можно поставить задержку sleep(Int) после dataTask.resume(), но что если её не хватит…

Вот пример метода:

static func requestData(completion: @escaping ([DataObject]?) -> ()) {
    var myData: [DataObject] = []
    let request = NSMutableURLRequest(url: NSURL(string: "https://mysite/api/data")! as URL,
                                      cachePolicy: .useProtocolCachePolicy,
                                      timeoutInterval: 10.0)
    request.httpMethod = "GET"
    let session = URLSession.shared
    let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { data, response, error in
        if error != nil { return }
        if data != nil {
            do {
                let dataArray = try JSONSerialization.jsonObject(with: data!, options: [])
                guard let jsonArray = dataArray as? [[String: Any]] else { return }
                for i in jsonArray {
                    let dataId = i["Id"] as! Int
                    let dataName = i["Name"] as! String
                    let object = DataObject(id: dataId, name: dataName)
                    myData.append(object)
                }
            } catch {
                print("Error")
                print(error as Any)
            }
        }
    })
    dataTask.resume()
    completion(myData)
}

#2

Покажите на весь экран view с progressBar’ом и уберите его, когда запрос закончится, если вы хотите что бы пользователь ничего не смог нажать, пока идет процесс загрузки.


#3

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


#4

Ах в этом плане. Тогда вам нужно поместить свой completion в конец обработки данных, т.е. в dataTask, после цикла for.

P.S. и скорее всего так же нужно добавить completion([]) в условие error != nil, перед return. Если вам нужно так же запустить свой блок с пустыми данными, в случае ошибки.


#5

Сделал вот так, не помогло.
PS. Помогло, но немного странно. Таблица с данными обновляется только при этапе на неё или когда скролить начинаешь.

static func requestData(completion: @escaping ([DataObject]?) -> ()) {
    var myData: [DataObject] = []
    let request = NSMutableURLRequest(url: NSURL(string: "https://mysite/api/data")! as URL,
                                      cachePolicy: .useProtocolCachePolicy,
                                      timeoutInterval: 10.0)
    request.httpMethod = "GET"
    let session = URLSession.shared
    let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { data, response, error in
        if error != nil { return }
        if data != nil {
            do {
                let dataArray = try JSONSerialization.jsonObject(with: data!, options: [])
                guard let jsonArray = dataArray as? [[String: Any]] else { return }
                for i in jsonArray {
                    let dataId = i["Id"] as! Int
                    let dataName = i["Name"] as! String
                    let object = DataObject(id: dataId, name: dataName)
                    myData.append(object)
                }
completion(myData)
            } catch {
                print("Error")
                print(error as Any)
            }
        }
    })
    dataTask.resume()

#6

Немного поработал с потоками и теперь всё обновляется.
Спасибо огромное, я из-за такой мелочи весь инет перерыл.