Ios Swift-URLSession任务中的TableView数据源
我必须用Ios Swift-URLSession任务中的TableView数据源,ios,swift,uitableview,asynchronous,Ios,Swift,Uitableview,Asynchronous,我必须用URLSession任务获取的一些数据填充TableView。源代码是一个XML文件,因此我将其解析为任务。解析的结果是一个数组,我将它传递给另一个函数,该函数填充了TableView委托使用的另一个数组 func checkInstalledApps(apps: NSMutableArray){ .... installedApps.add(...) installedApps.add(...) .... } 我的问题是任务结束前会调用
URLSession任务获取的一些数据填充TableView
。源代码是一个XML文件,因此我将其解析为任务。解析的结果是一个数组,我将它传递给另一个函数,该函数填充了TableView委托使用的另一个数组
func checkInstalledApps(apps: NSMutableArray){
....
installedApps.add(...)
installedApps.add(...)
....
}
我的问题是任务结束前会调用TableView委托
,因此启动应用程序时该表为空,除非重新加载数据(因此我知道解析和任务工作正常)
这里是viewDidLoad
函数listOfApps
是我的TableView
override func viewDidLoad() {
super.viewDidLoad()
fetchData()
checkInstalledApps(apps: <ARRAY POPULATED>)
listOfApps.delegate = self
listOfApps.dataSource = self
}
}
而checkInstalledApps
是我组成TableView委托使用的数组的函数
func checkInstalledApps(apps: NSMutableArray){
....
installedApps.add(...)
installedApps.add(...)
....
}
因此,例如,要设置我计数的行数installedApps
元素
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if (installedApps.count == 0) {
noApp = true
return 1
}
return installedApps.count
}
那是0。显然,如果我重新加载数据,一切正常
我的问题是异步调用:首先,我使用了一个可通过GET请求访问的XML,因此我可以使用XMLParser(contentsOf:myUrl)
,时间不是问题。也许如果XML能够成熟起来,我也会遇到一些麻烦,但现在我不得不使用POST请求
我已尝试使用DispatchGroup
,使用了
group.enter()
在super.viewDidLoad
group.leave()
在task.resume()之后
group.wait()
aftercheckInstalledApps()
其中group为让group=DispatchGroup()
,但不包含任何内容
那么,我如何告诉tableview委托等待任务响应和下一个函数呢
提前感谢我会忘记DispatchGroup
,并改变这里的思维方式(在收到响应之前,您不想冻结UI)
我相信您可以让fetchData
实现保持原样
在XMLParserDelegate.parserdenddocument(:)
中,将通知您XML已被解析。在该方法中,调用选中InstalledApps
,以填充模型数据。之后,只需调用listOfApps.reloadData()
,告诉tableView使用新数据重新加载
您希望在主线程上调用checkInstalledApps
和listOfApps.reloadData()
(使用DispatchQueue.main.async{}
)
同时保持listOfApps.delegate=self
和listOfApps.dataSource=self
在viewDidLoad
中保持现在的状态。更干净的方法是使用空状态视图/activityIndicator/loader/progress hud(无论您想要什么),通知用户应用程序正在获取/加载数据
获取完成后,只需重新加载tableview并删除空的状态视图/加载程序即可。您的问题是因为您目前无法知道URLSession
任务何时结束。reloadData()
下面是发生的情况的简化图:
完成块在这里提供了一个易于实现的解决方案。下面是一个非常简单的解决方案(可能不完整,因为我没有关于实际xml解析的所有细节):
func fetchData(completion: @escaping () -> Void) {
let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
self.parser = XMLParser(data: data!)
self.parser.delegate = self
completion()
}
override func viewDidLoad() {
super.viewDidLoad()
fetchData() { [weak self] in self?.tableView.reloadData() }
}
基本上,完成块将完成xml数据返回链