.reloadData() 没有重新创建可见单元格或内存中的单元格?
Posted
技术标签:
【中文标题】.reloadData() 没有重新创建可见单元格或内存中的单元格?【英文标题】:.reloadData() without reCreating visible cells or those who are in memory? 【发布时间】:2018-02-07 12:31:33 【问题描述】:当我实例化第三个单元格后,我将向我的模型数组中添加更多项目,然后我将更新集合视图数据:
DispatchQueue.main.async(execute:
self.collectionView.reloadData()
)
一切都按预期进行。但是,当我为我的 collectionView 重新加载数据时,它将实例化当前可见或保存在内存中的单元格 (2,3)。不幸的是,我有一些耗费大量时间的昂贵的服务器请求。
Instaniated 0
Instaniated 2
Instaniated 3
******polluting more data: size of cells 10
Instaniated 2
Instaniated 3
Instaniated 4
如何在不重新创建可见单元格或内存中的单元格的情况下重新加载数据?
非常感谢。
【问题讨论】:
然后缓存来自 API 的响应,如果每次都重新获取成本太高。 【参考方案1】:不要重新加载单元格,而是尝试插入或重新加载实际更改过的单元格。您可以为此使用UIColletionView
s performBatchUpdates(_:)
:Link
一个例子:
collectionView.performBatchUpdates
self.collectionView.insertItems(at: [IndexPath(row: 1, section: 1)])
这可确保仅加载新单元格。您还可以在此方法中移动单元格和部分,甚至删除单元格。链接页面包含所有这些的文档。
【讨论】:
感谢您的帮助! - 不幸的是,我收到以下错误:更新后现有部分中包含的项目数 (10) 必须等于更新前该部分中包含的项目数 (5),加上或减去插入的项目数或从该部分中删除。 @JulieNoobie 您在数组中的相同索引处插入了相同的值,因此numberOfCells
计数也是可维护的,并且您的数据数组的顺序与您希望在 tableView 上表示的顺序相同。希望你能明白。【参考方案2】:
为什么你不能采用下面的方法
1) 我希望您已将 dataSource 和 collectionView 对象声明为类的全局对象
let collectionView = UICollectionView()
var dataSource = [Any]()
2) 有一个函数可以从 API 响应中获取初始结果
func getInitialPosts()
// call api
// store your initial response in the local array object and reload collectionview
let results:[Any] = response from the server call
self.dataSource.append(contentsOf: results)
DispatchQueue.main.async(execute:
self.collectionView.reloadData()
)
3) 下次调用,可以有另一个函数
func getPostsForPage(page:Int)
// call api with page number
let newResults = response from the server call
self.dataSource.append(contentsOf: newResults)
var indexPathsToReload = [IndexPath]()
let section = 0
var row = self.dataSource.count - 1
//add new data from server response
for _ in newResults
let indexPath = IndexPath(row: row, section: section)
row+=1
indexPathsToReload.append(indexPath)
// perform reload action
DispatchQueue.main.async(execute:
self.collectionView.insertItems(at: indexPathsToReload)
)
【讨论】:
【参考方案3】:假设您正在从您的网络适配器调用委托函数 fetchData 并使用新数据。在这里你必须检查你的数据是否为空,以检查你是否需要添加新数据,或者重新加载整个 CollectionView。
然后,您创建所有需要获取更多的 indexPath,以便让已获取的单元格保持原样。最后使用 insertItems(at: IndexPaths)。
我使用 page 以便将来用页码对新数据进行分页。严格用于我的用例。祝你好运!
func fetchData(with videos: [VideoModel], page: Int)
guard self.data.count == 0 else
self.addNewData(with: videos, page: page)
return
self.data = videos
DispatchQueue.main.async
self.isPaging = false
self.collectionView?.reloadData()
self.page = page
func addNewData(with videos: [VideoModel], page: Int)
var indexPathsToReload = [IndexPath]()
let section = 0
var row = self.data.count - 1
self.data += videos
for _ in videos
print(row)
let indexPath = IndexPath(row: row, section: section)
row+=1
indexPathsToReload.append(indexPath)
DispatchQueue.main.async
self.isPaging = false
self.collectionView!.insertItems(at: indexPathsToReload)
self.page = page
【讨论】:
以上是关于.reloadData() 没有重新创建可见单元格或内存中的单元格?的主要内容,如果未能解决你的问题,请参考以下文章
使用自我调整大小的单元格后,reloadData 不再起作用
UITableView, reloadData 重新加载单元格但不调整表格大小
iOS - [UITableView reloadData] 重新加载,但不删除旧单元格?