Ios 在处理HTTP请求后重新加载UITableView
假设我有两个类:一个类表示执行HTTPGET请求的数据库Ios 在处理HTTP请求后重新加载UITableView,ios,swift,uitableview,Ios,Swift,Uitableview,假设我有两个类:一个类表示执行HTTPGET请求的数据库 func getObjects(completion: (([Object]) -> Void)?) { guard let url = // ... let session = URLSession(configuration: .default) let task = session.dataTask(with: url) { (data, response, error) in Dispatch
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)
}
加载和“格式化”工作正常
我在viewwillispect()
中调用load(then:)
函数,将结果传递给类数组,该数组保存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
,但没有成功。由于您发出了多个请求,因此在所有请求完成之前,您确实不想调用然后
闭包。您可能需要使用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是异步的,因此数据库调用应该在该函数的
完成回调中进行。由于您发出了多个请求,在所有请求完成之前,您确实不想调用然后闭包。您可能需要使用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是异步的,因此数据库调用应该在该函数的完成回调中进行。url请求是否有任何错误?因此,如果我理解正确,问题是您正在发出多个请求,并且希望在所有请求完成后重新加载表视图?url请求是否有任何错误?因此,如果我理解正确,问题是您正在发出多个请求,并且希望在所有请求完成后重新加载表视图?由于loadDatabaseConfigs似乎是异步的,因此最好将所有内容都移动到完成中closure@Macistador没错。我没注意到,谢谢你。我仍然不确定将self.tableView.reloadData()放在哪里。除此之外:您确定进入和离开调度组属于for循环而不是它的外部吗?您需要为每个getObjects调用匹配enter()和leave()调用,并且需要在每个配置的getObjects调用完成时执行leave()。如果在循环之外执行,则使用DispatchGroup没有任何意义,因为它将在同一runloop内进入和离开,导致立即执行其notify回调。您不需要将调用移动到self.tableView.reloadData()。保持原样。由于loadDatabaseConfigs似乎是异步的,所以最好将所有内容都移动到完成中closure@Macistador没错。我没注意到,谢谢你。我仍然不确定将self.tableView.reloadData()放在哪里。除此之外:您确定进入和离开调度组属于for循环而不是它的外部吗?您需要为每个getObjects调用匹配enter()和leave()调用,并且需要在每个配置的getObjects调用完成时执行leave()。如果在循环之外执行,则使用DispatchGroup没有任何意义,因为它将在同一runloop内进入和离开,导致立即执行其notify回调。您不需要将调用移动到self.tableView.reloadData()。放在原处。