ios - 从 UIDocument 获取单元格数据时,如何确保 UITableView 中显示的列表顺序

标签 ios swift uitableview 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
}

我希望单元格按照"file"的顺序呈现,但是,似乎顺序有点不可预测,假设这是因为“cellForRowAt”在知道完整的“cellsData”集之前被调用'.

最佳答案

来自 UIdocument 上的 Apple 文档。 Apple doc :

open(completionHandler:)

Opens a document asynchronously.

这意味着即使您以正确的顺序触发 document.open,也无法保证 completionHandler 序列将以相同的顺序,这就是顺序的原因是不可预测的

但是,您知道它们最终都会完成。

你可以做的是:

1 - 将打开文档中的所有数据放入另一个列表

2 - 根据您的需要排序此列表

3 - 将此列表放入 cellsData(我假设它已绑定(bind)到您的 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,这是一种等待你触发的所有异步操作完成后再执行某些操作(例如在这种情况下重新加载你的tableview)的方法(阅读: Raywenderlich tuts )

关于ios - 从 UIDocument 获取单元格数据时,如何确保 UITableView 中显示的列表顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57583814/

相关文章:

ios - 插入大约 10000 个数据大约需要 60 - 70 秒。我需要提交交易吗?

ios - 您可以在 Apple Push Notification 中塞入多少个字符?

swift - 在主应用程序和今日小部件 macOS 之间共享数据

ios - 滚动时 UITableViewCell 图像无法正确显示

ios - 使用 Swift 的 UICollectionView

ios - Xcode - 您的帐户中没有注册任何设备 - 解决方法?

ios - 如何从 SwiftUI 中的列表获取屏幕行?

ios - 如何在iOS中运行相互依赖的长时间运行任务

ios - Swift:ImageView 方面填充错误

Swift 为什么从 Parse 检索数据时我必须按两次按钮才能在 tableview 中加载数据