怎么解决UITableView 滑动卡顿问题

1.最常用的就是cell的重用, 注册重用标识符
  • 如果不重用cell时,每当一个cell显示到屏幕上时,就会重新创建一个新的cell
  • 如果有很多数据或者滚动cell的时候,就会堆积很多cell。如果重用cell,为cell创建一个ID
  • 每当需要显示cell 的时候,都会先去缓冲池中寻找可循环利用的cell,如果没有再重新创建cell
2.避免cell的重新布局
  • cell的布局填充等操作 比较耗时,一般创建时就布局好
  • 如可以将cell单独放到一个自定义类,初始化时就布局好
3.提前计算并缓存cell的属性及内容
  • 当我们创建cell的数据源方法时,编译器并不是先创建cell 再定cell的高度
  • 而是先根据内容一次确定每一个cell的高度,高度确定后,再创建要显示的cell,滚动时,每当cell进入凭虚都会计算高度,提前估算高度告诉编译器,编译器知道高度后,紧接着就会创建cell,这时再调用高度的具体计算方法,这样可以方式浪费时间去计算显示以外的cell
4.减少cell中控件的数量
  • 尽量使cell得布局大致相同,不同风格的cell可以使用不用的重用标识符,初始化时添加控件,
  • 不适用的可以先隐藏
  • 我们在cell上添加系统控件的时候,实际上系统都会调用底层的接口进行绘制,大量添加控件时,会消耗很大的资源并且也会影响渲染的性能。当使用默认的UITableViewCell并且在它的ContentView上面添加控件时会相当消耗性能。所以目前最佳的方法还是继承UITableViewCell,并重写drawRect方法。
  • 在实现drawRect方法的时候,它的参数rect就是我们需要绘制的区域,在rect范围之外的区域我们不需要进行绘制,否则会消耗相当大的资源。
5.离屏渲染的问题
  • 渲染耗时比较长
    • 为图层设置遮罩(layer.mask)
    • 将图层的layer.masksToBounds / view.clipsToBounds属性设置为true
    • 将图层layer.allowsGroupOpacity属性设置为YES和layer.opacity小于1.0
    • 为图层设置阴影(layer.shadow *)。
    • 为图层设置layer.shouldRasterize=true
    • 具有layer.cornerRadius,layer.edgeAntialiasingMask,layer.allowsEdgeAntialiasing的图层
    • 文本(任何种类,包括UILabel,CATextLayer,Core Text等)。
    • 使用CGContext在drawRect :方法中绘制大部分情况下会导致离屏渲染,甚至仅仅是一个空的实现
    • 不要使用ClearColor,无背景色,透明度也不要设置为0
6.使用局部更新
  • 如果只是更新某组的话,使用reloadSection进行局部更新
7.加载网络数据,下载图片,使用异步加载,并缓存
  • 我们时常会看到这样一个现象,就是加载时整个页面卡住不动,怎么点都没用,仿佛死机了一般。原因是主线程被阻塞了。所以对于网路数据的请求或者图片的加载,我们可以开启多线程,将耗时操作放到子线程中进行,异步化操作。这个或许每个iOS开发者都知道的知识,不必多讲。
8.少使用addView 给cell动态添加view
  • 在初始化cell的时候就将所有需要展示的添加完毕,然后根据需要来设置hide属性显示和隐藏。

9.按需加载cell,cell滚动很快时,只加载范围内的cell
  • 滑动很快时,只加载目标范围内的cell,这样按需加载(配合SDWebImage),极大提高流畅度。

10.不要实现无用的代理方法,tableView只遵守两个协议
11.缓存行高:
  • 如果cell高度不动态变化,可设置预估行高来减少计算量,cell行高的计算比较消耗性能
  • 如果cell高度动态变化,提高cell高度的计算效率之外,对于已经计算出的高度,我们需要进行缓存,对于已经计算过的高度,没有必要进行计算第二次。
  • estimatedHeightForRow不能和HeightForRow里面的layoutIfNeed同时存在,这两者同时存在才会出现“窜动”的bug。所以我的建议是:只要是固定行高就写预估行高来减少行高调用次数提升性能。如果是动态行高就不要写预估方法了,用一个行高的缓存字典来减少代码的调用次数即可
  • 值得注意的是,设置了预估行高和没设置预估行高,tableview代理的执行顺序不一样
12.其他方案:
  • 当我们需要圆角效果时,可以使用一张中间透明图片蒙上去
  • 使用ShadowPath指定layer阴影效果路径
  • 使用异步进行layer渲染(Facebook开源的异步绘制框架AsyncDisplayKit)
  • 设置layer的opaque值为YES,减少复杂图层合成
  • 尽量使用不包含透明(alpha)通道的图片资源
  • 尽量设置layer的大小值为整形值
  • 直接让美工把图片切成圆角进行显示,这是效率最高的一种方案
  • 很多情况下用户上传图片进行显示,可以让服务端处理圆角
  • 使用代码手动生成圆角Image设置到要显示的View上,利用UIBezierPath(CoreGraphics框架)画出来圆角图片

 
在iOS应用中,UITableView应该是使用率最高的视图之一了。几乎所有自带的应用中都能看到它的身影,一些常见的应用(QQ/微信/天猫)也离不开他的身影。
然而在使用第三方应用时,却经常遇到性能上的问题,普遍表现在滚动时比较卡,特别是table cell中包含图片的情况时。
以上方案可解决大部分tableView卡顿问题,在优化tableView的时候,针对性的优化一下,这种问题就不会存在


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 iOS 开发中,嵌套在 `UIScrollView` 中的 `UITableView` 在滑动时可能会与 `UIScrollView` 的滑动手势产生冲突,导致无法正常滑动。这个问题可以通过以下两种方式解决: 1. 禁用 `UIScrollView` 的滑动手势 可以通过设置 `UIScrollView` 的 `panGestureRecognizer` 的 `enabled` 属性为 `NO` 来禁用滑动手势,这样就不会与 `UITableView` 的滑动手势产生冲突了。 ```objc scrollView.panGestureRecognizer.enabled = NO; ``` 2. 实现 `UIGestureRecognizerDelegate` 协议的方法 在 `UIViewController` 中实现 `UIGestureRecognizerDelegate` 协议的 `gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:` 方法,可以控制两个手势是否允许同时识别。在这个方法中,可以判断当前的手势是否为 `UIScrollView` 的滑动手势,如果是,则允许与 `UITableView` 的滑动手势同时识别,否则不允许。 ```objc - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { if ([gestureRecognizer.view isKindOfClass:[UIScrollView class]] && [otherGestureRecognizer.view isKindOfClass:[UITableView class]]) { return YES; } return NO; } ``` 需要注意的是,在实现这个方法时,要将 `UIScrollView` 的 `delegate` 设置为当前的 `UIViewController`,否则这个方法不会被调用。 ```objc scrollView.delegate = self; ``` 以上两种方式都可以解决嵌套在 `UIScrollView` 中的 `UITableView` 滑动手势冲突的问题

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值