reloadData 与准确获取 contentSize

针对 UIScrollView 的 Category 获取的 contentSize 老是不准确,到底是为什么呢?让我们来一探究竟。

背景

由于上拉刷新底部的 noMoreDataView 的位置是以 scrollview 的 contentSize.height 作为 top 的,所以需要获取对应 contentSize 作为基准。

过程

业务场景中,往往是在请求数据成功的 block 中做相应的数据解析,刷新 UI,结束一些上下拉等动画的操作。这里其实会有一些问题:

  1. 刷新 UI 中的 reloadData 操作是需要在主线程中做的,而现在的大多数情况是在请求数据成功时的 block 里去刷新
  2. 上拉动画结束时,需要获取 scrollview 的 contentSize.height 去调整 noMoreDataView 的位置,而此时也是在请求数据的 block 中获取的,所以其实是不准的

解决方案

  1. reloadData 方法是需要在主线程执行,所以可以将获取属性值的操作放在 GCD 的主线程异步执行(俗称:runloop 大法)
1
2
3
dispatch_async(dispatch_get_main_queue(), ^{
// self.contentSize.height
})
  1. 即使使用了 runloop 大法,获取的 contentSize 还是不准确。 UICollectionViewUITableView 虽然都继承自 UIScrollView,但是 UICollectionView 有自己的 contentSize 获取方法(通过 collectionViewLayout 去获取):
1
self.collectionView.collectionViewLayout.collectionViewContentSize.height

PS

附上苹果官方的开发者文档,可以从 contentSize 的各自命名上感受下差别(只能理解为 UICollectionView 是更高维度的 UIScrollView,虽然 UICollectionView 继承自 UIScrollView):

另外,block 内调用主线程的操作,stackoverflow 上也有相应的讨论

文章目录
  1. 1. 背景
  2. 2. 过程
  3. 3. 解决方案
  4. 4. PS