1.dalegate和datasource的执行顺序和执行次数
numberOfSectionsInTableView
tableView:heightForHeaderInSection //这里这个方法连续调用了两次
tableView:heightForFooterInSection //这里这个方法也连续调用了两次
tableView:numberOfRowsInSection
上边这个顺序重复了四次后开始调用获取cell和cell高度的方法
tableView:cellForRowAtIndexPath
tableView:heightForRowAtIndexPath
先获取cell,再计算高度
2.预算高度是干嘛的,估算不准会出现什么情况
因为UITableview是个UIScrollView,加载时需要先知道自己的contentSize后,再根据自己的bounds,contentInset,contentOffSet,等属性共同决定,是否可以滑动,以及滚动条的长度。而UITableView一开始并不知道自己有多少内容,需要通过dalegate,dataSource的方法调用才能知道,这样就造成他在加载的时候就浪费了多余的计算在屏幕显示外的cell上了。
设置的估算高度如果不准,因为滑动的时候实时更新着cell的高度,那么contentSize也就会跟着实时变化,这时候滚动条就会出现肉眼可见的突然变化,甚至是跳跃。
3.为何tableview在reloadData后要先计算高度
数据源变更后,需要将所有显示的UITableViewCell和未显示可复用的UITableViewCell全部从父视图移除,重新创建,重新创建肯定需要先计算高度,来重新设置contentSize,因为UIScrollView加载需要知道contentSize。
4.cell的复用原理。(如何判断cell出去了屏幕)
_reusableTableCells_visibleCells
如何判断当前是否出去了屏幕?
通过滚动偏移量获取当前显示的bounds ,CGRectMake(0,contentOffset,tableview.width,tableview.height); 获取当前cell的rect 然后相比较.
5.如何避免tableview的卡顿
CPU:
1)缓存高度
2)cell界面复杂考虑frame布局
3)复用cell时应尽量避免new出cell中使用的对象,应考虑复用
4)高度变化不大,考虑预算高度
5)如果图片过大,要考虑在sdwebimage缓存图片之前将图片压缩
GPU:尽可能避免离屏渲染
1)圆角
2)透明度
3)阴影
6.想在tableview reloadData完之后做某些操作的方法
方法一: [self.tableView reloadData];
[self.tableView layoutIfNeeded];
//doSomething
方法二: [self.tableView reloadData];
dispatch_async(dispatch_get_main_queue(), ^{
//doSomething
});
7.简述如何实现一个Tableview。 参考了Chameleon源码和本篇文章以及这边文章的注解
1)首先看初始化方法中三个比较有用的属性。除了做了一些基本属性的初始化之外,还初始化了三个比较重要的属性cachedCells sections reusableCells。 然后标记了needsReload。
2)然后是调用设置 数据源和代理的方法。我们发现当设置了数据源之后,代码中又一次设置了needsReload的标志。告诉NSRunLoop数据源已经设置好了,需要在下一次循环中使用数据源进行布局。
_dataSourceHas 和 _dataDelegateHas 是一个用于记录该数据源或者代理实现了哪些方法的结构体,该结构体源码如下:
其实也可以使用布尔值的属性来表示,但是布尔变量占用的内存大小为一个字节即8byte,但是该结构体用一个byte来记录,大大缩小了占用的内存。
?xml version="1.0" encoding="UTF-8"?
3)接下来看下_setNeedsReload的源码
其实就是将needsReload标记为yes 然后调用setNeedsLayout方法,之后NSRunloop会在下一次循环中自动调用layoutSubviews方法。
4)那么UITableview的layoutSubviews方法中到底做了什么?
5)下面来看看reloadData方法的实现
其中_updateSectionsCache方法是最重要的一个方法。
该方法会在调用reloadData方法之后,清除之前缓存的sections信息,然后根据dataSource来计算每一个UITableViewSection的所有信息,包括header的view,title,height,以及section下所有行的总高度rowsHeight,然后将UITableViewSection对象放到_sections数组中进行缓存。这些缓存的数据用于后边对tableview的布局。
6)最后就是UITableView最核心的方法_layoutTableView。
_sections中存储的就是UITableViewSection的实例对象,其中每一行的高度存储在了一个数组当中 rowHeights。
_reusableCells 到底是如何使用的?
在_layoutTableView方法中对cell进行布局的时候。cell的获取方式有两种,如果在当前可视区域内存在直接从availableCells中获取,如果不存在是通过数据源实现的cellForRowAtIndexPath方法中获取的。
该方法中通常会调用- (UITableViewCell*)dequeueReusableCellWithIdentifier:(NSString*)identifier方法。那么我们看看该方法的实现。
网友评论