[英]How to ensure the order of list shown in UITableView when getting data for cell from UIDocument
我的应用程序通过FileManager为UITableView中的每个单元获取数据。 单元格需要来自需要打开UIDocument对象的文件中的数据。 但是,似乎打开完成处理程序中的代码无法预料地执行,因此单元格不会按我希望的顺序显示。
我该如何解决这个问题? 如果有人提供任何线索,我将不胜感激。
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
fetchCellsData()
}
func fetchCellsData() {
do {
let files = getUrlsOfFiles() //files in a certain order
for file in files {
let document = MyDocument(fileURL: file) //MyDocument subclassing UIDocument
//open to get data for cell
document.open { (success) in
if !success {
print("File not open at %@", file)
return
}
let data = populateCellData(document.fileInfo)
self.cellsData.append(data)
self.tableView.reloadData()
/// tried below also
// DispatchQueue.main.async {
// self.cellsData.append(data)
// self.tableView.reloadData()
// }
}
document.close(completionHandler: nil)
}
} catch {
print(error)
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! MyCell
let fileInfo = cellsData[indexPath.row].fileInfo
//assign fileInfo into MyCell property
return cell
}
我预计单元格将按照“文件”的顺序进行渲染,但是,假设顺序是有点不可预测的,因为这是由于在知道完整的“ cellsData”集之前调用了“ cellForRowAt”这一事实。
摘自UIdocument
上的Apple文档。 苹果文档 :
打开(completionHandler :)
异步打开文档。
这意味着,即使您以正确的顺序触发document.open
,也无法保证completionHandler
序列的顺序相同,这就是为什么该顺序不可预测的原因 。
但是,您知道他们最终将全部完成。
您可以做的是:
1-将打开的文档中的所有数据放入另一个列表
2-根据您的需要order
此清单
3-将此列表放入cellsData
(我假设已绑定到您的tableViesDatasource)
var allDatas: [/*your data type*/] = []
...
do {
// reset allDatas
allDatas = []
let files = getUrlsOfFiles()
for file in files {
let document = MyDocument(fileURL: file)
document.open { (success) in
if !success {
print("File not open at %@", file)
return
}
let data = populateCellData(document.fileInfo)
self.allDatas.append(data) // "buffer" list
self.tableView.reloadData()
}
document.close(completionHandler: nil)
}
} catch { ...
然后,将cellsData
更改为如下所示的计算属性:
var cellsData: [/*your data type*/] {
get {
return allDatas.order( /* order in accordance to your needs */ )
}
}
这样,每次添加新数据时,列表都是排序器,然后重新显示。
讨论区
这是关于代码状态的更简单的解决方案,但是,这可能不是整体的首选解决方案。 例如,在您的代码中,您每次添加新值时都会重新加载tableview,因为您知道之后会添加更多数据,而这些数据并未进行优化。
我建议您阅读Dispatch Group ,这是一种在执行某些操作之前等待触发的所有异步操作完成(例如在这种情况下重新加载表格视图 )的一种方法(阅读: Raywenderlich tuts )
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.