处理HTTP请求后重新加载UITableView

时间:2019-02-12 09:30:42

标签: ios swift uitableview

比方说,我有两个类:一个类代表我执行HTTP GET请求的数据库。

func getObjects(completion: (([Object]) -> Void)?) {

  guard let url = // ...

  let session = URLSession(configuration: .default)
    let task = session.dataTask(with: url) { (data, response, error) in
      DispatchQueue.main.async {
        if let error = error {
          fatalError("Dispatching main queue failed: \(error)")
        } else if let data = data {
          let decoder = JSONDecoder()

          do {
            let objects = try decoder.decode([Object].self, from: data)
            completion?(object)
          } // ...
    // ...
    }
  task.resume()
}  

将相应的结果对象数组传递给另一个类的UIViewController。因为我基于不同的配置对象实例化了多个数据库,所以我想显示按UITableView节排序的结果。

func load(then: (([(DatabaseConfig?, [Object])]) -> Void)) {
  var allObjects: [(DatabaseConfig?, [Object])] = [(nil, [])]

  Storage.loadDatabaseConfigs(completion: { configs in
    self.configs = configs
  })

  for config in self.configs {
    var objectSection: (DatabaseConfig?, [Object]) = (nil, [])

    let database = Database.init(config: config)

    objectSection.0 = config
    database.getObjects(completion: { objects in
      objectSection.1.append(objects)
    })
    allObjects.append(allObjectsInSection)
  }

  then(allObjects)
}

加载和“格式化”有效。

我在load(then:)中调用viewWillAppear()函数,在这里将结果传递给类数组,该类数组包含TableView的所有最终条目。然后,我尝试重新加载数据。

override func viewWillAppear(_ animated: Bool) {
  super.viewWillAppear(true)
    self.load(then: { objects in
      self.allObjects = objects
      self.tableView.reloadData()
    })
}

我知道GET请求需要时间,所以我的问题是:如何或在何处重新加载UITableView?我显然需要确定GET请求已执行成功,然后重新加载。我已经尝试调用DispatchQueue.main.async进行重新加载,但这没有用。

1 个答案:

答案 0 :(得分:2)

由于您发出了多个请求,因此您确实不希望在所有请求完成之前调用then闭包。您可能为此使用DispatchGroup

func load(then: (([(DatabaseConfig?, [Object])]) -> Void)) {
    var allObjects: [(DatabaseConfig?, [Object])] = [(nil, [])]

    Storage.loadDatabaseConfigs(completion: { configs in
        self.configs = configs

        let dispatchGroup = DispatchGroup()
        for config in self.configs {
            dispatchGroup.enter()
            var objectSection: (DatabaseConfig?, [Object]) = (nil, [])

            let database = Database.init(config: config)

            objectSection.0 = config
            database.getObjects(completion: { objects in
                objectSection.1.append(objects)
                dispatchGroup.leave()
            })
            allObjects.append(allObjectsInSection)
        }
        dispatchGroup.notify(queue: .main) {
            then(allObjects)
        }
    })
}

编辑:如@Macistador所述,loadDatabaseConfigs是异步的,因此应在该函数的completion回调中进行数据库调用。