一.tableView的执行顺序:
————————————多少个分区重复执行—————————————
1. 有多少个分区。
- (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView
2. 估算header和Footer视图高度。(若没有,执行11,14)
- (CGFloat)tableView:(UITableView*)tableView
estimatedHeightForHeaderInSection:(NSInteger)section
- (CGFloat)tableView:(UITableView*)tableView
estimatedHeightForFooterInSection:(NSInteger)section
3. 每个分区有多少行
- (NSInteger)tableView:(UITableView*)tableView
numberOfRowsInSection:(NSInteger)section
4. 估算每个cell的高度(若没有,执行8)
- (CGFloat)tableView:(UITableView*)tableView
estimatedHeightForRowAtIndexPath:(NSIndexPath*)indexPath
-------------------------------------------------------------
5. 右边索引的titles。
- (nullableNSArray<NSString*> *)sectionIndexTitlesFor
TableView:(UITableView*)tableView
—————————————多少行重复执行—————————-———
6. 每个cell的内容。
- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
7. 设置indexPath上的每一行的cell的缩进
- (NSInteger)tableView:(UITableView*)tableView indentationLevelForRowAtIndexPath:(NSIndexPath*)indexPath
8. 依次计算可视区域里每个cell的高度
- (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath
9. 某一行是否可以编辑(删除)
- (BOOL)tableView:(UITableView*)tableView canEditRowAtIndexPath:(NSIndexPath*)indexPath
10.将要展示Cell视图
- (void)tableView:(UITableView*)tableView willDisplayCell:(UITableViewCell*)cell forRowAtIndexPath:(NSIndexPath*)indexPath
------------------------------------------------------------
11.header视图高度(若没有估算,即2,此方法已执行,不再执行)
- (CGFloat)tableView:(UITableView*)tableView
heightForHeaderInSection:(NSInteger)section
12.header视图内容(若没有视图,将显示header标题)
- (nullableUIView*)tableView:(UITableView*)tableView
viewForHeaderInSection:(NSInteger)section
- (NSString*)tableView:(UITableView*)tableView
titleForHeaderInSection:(NSInteger)section
13.将要展示header视图
- (void)tableView:(UITableView*)tableView
willDisplayHeaderView:(UIView*)view
forSection:(NSInteger)section
14.footer视图高度(若没有估算,即2,此方法已执行,不再执行)
- (CGFloat)tableView:(UITableView*)tableView
heightForFooterInSection:(NSInteger)section
15.footer视图内容(若没有视图,将显示footer标题)
- (nullableUIView*)tableView:(UITableView*)tableView
viewForFooterInSection:(NSInteger)section
- (NSString*)tableView:(UITableView*)tableView
titleForFooterInSection:(NSInteger)section
16.将要展示footer视图
- (void)tableView:(UITableView*)tableView willDisplayFooterView:(nonnullUIView*)view forSection:(NSInteger)section
二.tableView的优化
懒加载
懒加载也叫延迟加载, 或者通俗来讲就是用到时再去加载对象。
tableView的懒加载步骤:
1、在cellForRowAtIndexPath中,某一行的cell的image对象是否为空,若为空,在tableView不拖拽和暂停时,开始加载图片。(tableView.dragging == NO && tableView.decelerating == NO)。不为空,就直接将它赋值给cell的imageView对象,这样就能解决图片短暂重用问题。
2、当界面滑动或者滑动减速的时候,都不进行图片加载。 在停止拖拽和减速停止时下载屏幕可见行的图片。
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView
willDecelerate:(BOOL)decelerate。//停止拖拽的时候开始执行
- (void)scrollViewDidEndDecelerating:(UIScrollView *)
scrollView //减速停止的时候开始执行
3、可见行图片下载。屏幕可见行的图片下载。先取得屏幕可见的行数组,遍历数组里的图片有没有值,没值就下载。
注意:图片截取时直接设置截取会触发离屏渲染,比较消耗性能。一般我们用Core Graphics绘制圆角。
tableView缓存高度的步骤:
1、创建缓存的字典,Key:(cell标示,分区,行),Value:高度。
2、检查缓存的key对应的value里面有值没有,如果有,就取出来,考虑如果时64bit,用double,不是64位,用float。
3、如果没有,计算该cell的高度。
4、利用runtime取出tableView绑定的存有cell的字典。根据重用标示,从重用池中取出对应的cell,取后放回重用池。
5、计算cell的高度,计算高度时考虑到是否有约束条件。(//如果不是非自适应模式则添加约束后计算约束后高度,计算后移除约束。)
6、计算出来高度,缓存key对象的value里面。
优化方案:
1.缓存行高。因为当cell 多时,heightForRowAtIndexPath:是调用最频繁的方法。提前计算并缓存好高度。
2.不要动态创建子视图。显示、不显示控制。这样能尽可能的减少cell的创建,或从缓存池中取时因为布局子控件所消耗的时间。
3.所有的子视图都必须指定背景颜色。当从某个控制器A跳转到下一个控制器B时,若B控制器的view未设置背景颜色,跳转时会有卡顿现象,cell也一样,若控件未指定背景颜色,会影响tableView滚动的流畅度.
4.所有的颜色都不要使用alpha ,因为控件如有透明度,会显示底部控件的部分轮廓,系统在显示cell时,需要计算各控件间的叠加面积,颜色的透明度等;但如果所有控件颜色不透明,则不需要耗费性能去计算,能节省大量时间.
5.cell栅格化 栅格化,是UI设计师的术语:是将cell 中的所有内容,生成一张独立的图像,在屏幕滚动时,只显示图像 设置属性self.layer.shouldRasterize = YES;即可 栅格化的同时必须指定分辨率,否则默认使用1倍的scale 生成图像! 需要设置self.layer.rasterizationScale = [UIScreen mainScreen].scale;
6.异步绘制!如果cell 比较复杂,可以设置cell图层的属性self.layer.drawsAsynchronously = YES;
7.tableview加载图片的时候使用lazy(懒加载)模式和异步加载模式
8.正确使用reuseIdentifier来重用Cells 当一个tableView中有多种类型的cell时,需要定义不同的重用标识,确保在缓存池正确找到重用的cell.
补充:
#pragma mark - ---- ScrollView扩展响应Touch事件
//UISrollView的事件经常与其子view事件冲突,截断子view事件的相应,此方法可以传递touch事件
@implementation UIScrollView (UITouchEvent)
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[[selfnextResponder]touchesBegan:toucheswithEvent:event];
[supertouchesBegan:toucheswithEvent:event];
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
[[selfnextResponder]touchesMoved:toucheswithEvent:event];
[supertouchesMoved:toucheswithEvent:event];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[[selfnextResponder]touchesEnded:toucheswithEvent:event];
[supertouchesEnded:toucheswithEvent:event];
}
@end