UITableView优化浅析

优化的主要思路

  • 异步渲染内容到图片。
  • 按照滑动速度按需加载内容。
  •  重写处理网络图片加载。
  • 缓存一切可缓存的, 用空间换时间.(重用

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

1.重用cell

UITableViewCell的重用机制是最常见也是最有效的优化方式之一. 使用dequeueReusableCellWithIdentifier来实现布局相同的cell的重用, 也可以通过cellForRowAtIndexPath 直接复用某个cell. 如

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    WeiboTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
    if (cell == nil) {
        cell = [[WeiboTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];
    }
    [self drawCell:cell withIndexPath:indexPath];
    return cell;
]
注:因为cellForRowAtIndexPath方法调用非常频繁, 初始化,上下滚动,刷新都要调用. 所以cell的标示声明为静态变量更好。

2.避免cell的重新布局

cell的布局填充等操作比较耗时, 一般可在创建时就布局好. 如可将cell单独放到一个class中WeiboTableViewCell, 重写其initWithStyle方法, 在其中将cell的布局设置完成.
创建cell完成之后, 调用drawCell往其中填充内容即可, 即将cell的布局及填充分开执行, 且尽量将要填充的data提前准备好.

 (void)drawCell:(WeiboTableViewCell *)cell withIndexPath:(NSIndexPath *)indexPath {
    NSDictionary *data = [datas objectAtIndex:indexPath.row]; // 提前缓存好cell中的内容
    cell.selectionStyle = UITableViewCellSelectionStyleNone;

3.提前计算并缓存cell的属性及内容

因UITableView继承自UIScrollView, 因此其布局主要表现为Plain和Grouped两种风格. 需先确定其contentSize及每个cell的位置, 才会将其放进去. 如:

要显示100个cell,而当前屏幕只能显示5个. 则reload的时候,会先调用100次heightForRowAtIndexPath方法, 然后调用5次cellForRowAtIndexPath方法; 滚动屏幕时, 每当cell进入屏幕, 都会调用一次heightForRowAtIndexPath和cellForRowAtIndexPath方法.

  • cellForRowAtIndexPath和heightForRowAtIndexPath是调用最频繁的方法, 要尽量少地调用这两个方法.
  • cell填充与计算布局分离. cellForRowAtIndexPath只填充cell,heightForRowAtIndexPath负责计算高度, 将高度等布局缓存到数据源中.
  • 对于富文本AttributedString等cell中内容, 可提前创建好, 进行数据缓存, 然后需要时直接往cell中填充即可.
  • 使用estimatedRowHeight来预估高度, 防止浪费时间计算屏幕外边的cell, 如  self.tableView.estimatedRowHeight = 88.
  • cell内容的异步加载

                   如web的内容异步加载, 图片配合SDWebImage缓存, 将网络请求结果缓存.

4.subView的绘制

如果有多个不同风格的cell, 可以给每种cell指定不同的重用标识符. 然后使用dequeue每次将其出列使用即可.

  •  少用addView给cell动态添加view, 减少创建subview的数量如cell大致布局相同, 则可以只定义一种cell, 在初始化时添加, 通过hidden来控制其中内容的显示. 如有可能, 尽量缓存subview.
  •  慎用clearColor, 多个view层叠加渲染会消耗更多的时间, 所以尽量不要或者少用透明图层, 因系统将透明层与下面的view混合起来计算颜色, 渲染速度. 所以, 慎重使用clearColor.
  •  尽量将opaque设为YES, 尽量将subview的opaque设为YES, 避免GPU对cell其中的内容进行绘制.避免无用的CALayer渲染特效.
  •   需要绘制阴影的时候,通过指定阴影的路径提高效率.
  •     重载subView的drawRect方法如果定制cell的过程中需要多个小的元素的话,最好直接对要显示的多个项目进行绘制,而非采用添加多个subview

5.UITableView的局部更新

我们常用[self.tableView reloadData]来进行tableView中的数据更新. 如果只是更新某个section的话, 可以使用reloadSections等进行局部的更新

对于复杂的tableView界面, 可考虑异步绘制. 使用dispatch_async和dispatch_sync配合, 将业务逻辑与UI绘制分开

elf.tableView reloadRowsAtIndexPaths:<#(NSArray *)#> withRowAnimation:<#(UITableViewRowAnimation)#> 

[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationNone];

6.NSTimer在cell中的失效问题

NSTimer在UITableViewCell的重用中会失效, 所以不要将timer添加到cell中. 因在滑动tableView时, timer不会触发时间函数. 因它们使用共同的runloop, 而tableView的滑动阻止了timer的时间函数.
可以考虑:
1. 对于显示在cell中的text或其他对象上使用timer.
2. 并行实现, 主要是设置mode参数:

NSTimer* timer = [NSTimer timerWithTimeInterval:0.005 target:self selector:@selector(timerFireMethod:) userInfo:@"finishAnimation" repeats:YES];
    NSRunLoop *currentRunLoop = [NSRunLoop currentRunLoop];
    [currentRunLoop addTimer:timer forMode:NSRunLoopCommonModes];

7.优化touch事件传递

把不需要接受touch的view的userInteractionEnabled设为0.

8.estimatedRowHeight的使用

UITableView 是个 UIScrollView,就像平时使用 UIScrollView 一样,加载时指定 contentSize 后它才能根据自己的 bounds、contentInset、contentOffset 等属性共同决定是否可以滑动以及滚动条的长度。而 UITableView 在一开始并不知道自己会被填充多少内容,于是询问 data source 个数和创建 cell,同时询问 delegate 这些 cell 应该显示的高度,这就造成它在加载的时候浪费了多余的计算在屏幕外边的 cell 上。和上面的 rowHeight 很类似,设置这个估算高度有两种方法:

self.tableView.estimatedRowHeight = 88;
// or
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
    // return xxx
}
有所不同的是,即使面对种类不同的 cell,我们依然可以使用简单的estimatedRowHeight 属性赋值,只要整体估算值接近就可以,比如大概有一半 cell 高度是 44, 一半 cell 高度是 88, 那就可以估算一个 66,基本符合预期。

问题讨论:

  1. 设置估算高度后,contentSize.height 根据“cell估算值 x cell个数”计算,这就导致滚动条的大小处于不稳定的状态,contentSize 会随着滚动从估算高度慢慢替换成真实高度,肉眼可见滚动条突然变化甚至“跳跃”。
  2. 若是有设计不好的下拉刷新或上拉加载控件,或是 KVO 了 contentSize 或 contentOffset 属性,有可能使表格滑动时跳动



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!
提供的源码资源涵盖了小程序应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值