UICollectionView滑动流畅性优化
UICollectionView滑动流畅性优化
前言
初始的collection view在滑动时都是十分流畅的,然而因为collection view cell 加载更多的内容时因为主线程耗用太多性能而导致主线程出现堵塞,导致原本流畅的滑动出现卡顿的情况。

collection view加载cell时一般会常用复用池,所以滑动时每要显示一个cell都会调用协议中- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath;的方法,而在这方法中除了返回复用池中的cell,程序猿还可以趁机在其中调用cell自定义的读取数据的方法(姑且称之为-(void)loadData:),在本文中即将展示如何将- (void)loadData:中的耗时操作放入NSOperationQueue中并发进行从而不影响collection view的滑动,同时在用户快速滑动中,单个cell的NSOperationQueue中会堆积大量operation的情况,也将在本文中提出应对方法。
NSOperationQueue和NSInvocationOperation
NSOperationQueue将线程操作以队列的形式展现,初始化代码如下:
_queue = ({
NSOperationQueue *q = [[NSOperationQueue alloc]init];
//设置最大并行操作数为1相当于将queue设置为串行线程
q.maxConcurrentOperationCount = 1;
q;
});
每一个operation都是这个队列中的一个元素,而这个元素在满足条件的情况下可以在不用执行就从队列中移除,我们可以利用这种特性来取消其中一些未执行但是不必执行的operation ,关键代码如下:
if (self.operationQueue.operationCount >= 2) {
[self.operationQueue cancelAllOperations];
}
NSInvocationOperation *op = [[NSInvocationOperation alloc]
initWithTarget:self
selector:@selector(operationSelector:)
object:dic];
[self.operationQueue addOperation:op];
其中-(void)cancelAllOperations可以让队列里的所有待执行的operation移除出队列(详情看官方文档),要注意,如果执行此方法时有operation正在执行,那么那些正在执行的operation不会被强行中止并取消。
Canceling the operations does not automatically remove them from the queue or stop those that are currently executing. For operations that are queued and waiting execution, the queue must still attempt to execute the operation before recognizing that it is canceled and moving it to the finished state.——苹果官方开发文档
NSInvocationOperation是NSOperation的子类,它和NSBlockOperation一样都可以作为元素添加到NSOperationQueue中等待执行,最主要的区别在于前者带的是@selector后者带的是block。
异步操作中因视图原因导致程序崩溃时的应对方法
原本高高兴兴把耗时的代码都放到队列中运行时却发现在涉及到视图操作的地方容易出现错乱,甚至是BAD_XXXX之类的崩溃时,就需要检查@selector中是否包含类似addSubview,removeFromSubview之类的傻X操作(每读取一次数据就把view移出来/放进去是什么鬼操作?!View:我来了,我又走了,我来了,我又走了,你打我呀……),遇到这种代码第一想到的是尽量将其移出Operation,最好是将其放到初始化的方法,但是还有些情况是有些视图的属性受到数据的影响,需要等耗时操作结束之后才能确定视图的属性,这个时候就要用到GCD的方法了,如下:
- (void)optimizeOperation:(NSString *)dataStr {
//模拟十分耗时间的操作,注意,这里不能放在main_queue里面执行,否则时间还是消耗在了主线程里面
[NSThread sleepForTimeInterval:0.05];
if ([dataStr isEqualToString:self.dataStr]) {
dispatch_async(dispatch_get_main_queue(), ^{
self.titleLb.text = dataStr;
});
}
}
要注意dispatch_async(dispatch_get_main_queue(), ^{})中不要有耗时的方法,我们到目前为止的铺垫都是为了让占用主线程的滑动操作不要被其他操作堵塞,如果把耗时操作放进去的话就前功尽弃了。

附带demo地址,本文所涉及的思路体现在TextCell.m中:https://github.com/MrYu4/OptimizeCollectionView
可能存在的疑问
- 可是我就是不想用NSInvocationOperation啊,我用NSBlockOperation不行吗?
行
if (self.operationQueue.operationCount >= 2)这个判断语句怎么理解?
队列中如果有两个或两个以上个待出队列的
operation,那么第一个可能是正在执行中的,第二个或者之后都是未执行的(忘了说了,queue设置了最多可并发运行一个operation),这个时候正好是有新的operation等待加入,就说明以往的operation没什么用了,这个时候就可以进行剪枝操作,把operation除去节省性能。
- 接着上个问题,为什么不是>=1呢
[self.operationQueue cancelAllOperations];能立刻去除的是未执行的operation,但正在执行的不会除掉,也就是在cancelAllOperations之前队列内元素个数=1时,就基本上可以确定队列中没有可以除掉的operation了。
求打赏

UICollectionView滑动流畅性优化的更多相关文章
- UITableVIew 滚动流畅性优化
影响UITableViewUITableView滚动的流畅性原因: 1. 在代理方法中做了过多的计算占用了 UI 线程的时间 2.同上 3.Cell 中 view 的组织复杂,比如使用layer并不会 ...
- UITableView 滚动流程性优化
影响 UITableView 滚动的流畅性的原因 1. 在代理方法中做了过多的计算占用了 UI 线程的时间 2.同上 3.Cell 中 view 的组织复杂 关于第一点,首先要明白 tablevi ...
- iOS的流畅性
1优先级别不同:iOS最先响应屏幕 优先级别不同:iOS最先响应屏幕 当我们使用iOS或者是Android手机时,第一步就是滑屏解锁找到相应程序点击进入.而这个时候往往是所有操控开始的第一步骤,iOS ...
- 让页面滑动流畅得飞起的新特性:Passive Event Listeners
版权声明:本文由陈志兴原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/153 来源:腾云阁 https://www.qclo ...
- ios UICollectionView滑动时操作
点开UICollectionViewDelegate,发现有@protocol UICollectionViewDelegate <UIScrollViewDelegate>. 所以只要实 ...
- UIScrollView的delegate方法妙用之让UICollectionView滑动到某个你想要的位置
一个UICollectionView有好多个cell,滑动一下,谁也不知道会停留在哪个cell,滑的快一点,就会多滑一段距离,反之则会滑的比较近,这正是UIScrollview用户体验好的地方. 如果 ...
- Spring配置表友好性优化思路
Spring配置表需要尽量保证对程序员的友好性,一下提供一种优化思路. 中途未保存,心态炸了,只贴图了,fuuuuuuuuuuuuuck 第一种(最烂,最不友好):以Json的格式保存在配置表中,程序 ...
- Android Developers:使ListView滑动流畅
流畅滑动ListView的关键是保持应用程序的主线程(UI线程)从免于繁重处理.确保你的任何硬盘访问,网络访问或者SQL访问在一个单独的线程中.为了测试你的应用个程序的状态,你能启动StrictMod ...
- iOS开发之加载、滑动翻阅大量图片优化解决方案
本文转载至 http://mobile.51cto.com/iphone-413267.htm 今天分享一下私人相册中,读取加载.滑动翻阅大量图片解决方案,我想强调的是,编程思想无关乎平台限制.我要详 ...
- UI的流畅度优化
Android中所有的界面绘制工作都是在UI线程中进行的,提高UI流畅度的最核心根本在于释放UI线程.即:不在主线程中做耗时的操作. 很多人都知道,耗时的操作要放到子线程中去做,比如访问网络,比如读写 ...
随机推荐
- [FAQ] uni-app 运行微信小程序 main.wxss 报错 unexpected token "$"
检查一下你是否在 App.vue 中有手动操作引入过 uni.scss,比如下面的 import: <style lang="scss"> @import url(&q ...
- win10 uwp 简单制作一个 Path 路径绘制的图标按钮
本文告诉大家在 UWP 或 WinUI 3 里面如何简单制作一个由 Path 几何路径图形绘制的图标按钮 先在资源里面定义按钮的样式,重写 Template 属性,通过在 Template 里面放入 ...
- dotnet 6 已知问题 获取 CultureInfo.NumberFormat 可能抛出 IndexOutOfRangeException 异常
本文记录一个 dotnet 6 已知问题,准确来说这是一个在 dotnet 5 引入的问题,到 dotnet 6.0.12 还没修.在获取 CultureInfo.NumberFormat 属性时,在 ...
- Mysql5.7 Linux编译安装教程
1.系统约定 安装文件下载目录:/data/software Mysql目录安装位置:/usr/local/mysql 数据库保存位置:/usr/local/mysql/data 日志保存位置:/tm ...
- Arrays类的常用方法
Arrays类的常用方法 Array数组的工具类java.util.Arrays Arrays类中的方法都是static修饰的静态方法,在使用的时候可以直接使用类名进行调用,而不用使用对象来调用 Ar ...
- 简述 js 的代码整洁之道
文章参考出自:https://juejin.cn/post/7224382896626778172 前言 为什么代码要整洁? 代码质量与整洁度成正比.有的团队在赶工期的时候,不注重代码的整洁,代码写的 ...
- 用pageOffice文档控件实现 office文档在线编辑
第三方文档控件,pageOffice 系统开发中经常要处理办公文档,如果word,excel,ppt,编辑整理,保存,归档. 开发市场上也有很多第三文文档控件,多年的总结,还是认为pageOffice ...
- 【.NET项目分享】免费开源的静态博客生成工具EasyBlog,5分钟拥有自己的博客
EasyBlog 说明 本博客系统通过构建工具生成纯静态的博客网站,借助GitHub Pages,你可以在5分钟内免费拥有个人博客. 它具有以下特点 生成纯静态网站,访问速度极快 使用markdown ...
- 13年过去了,Spring官方竟然真的支持Bean的异步初始化了!
你好呀,我是歪歪. 两年前我曾经发布过这样的一篇文章<我是真没想到,这个面试题居然从11年前就开始讨论了,而官方今年才表态.> 文章主要就是由这个面试题引起: Spring 在启动期间会做 ...
- 轻松下载k8s.gcr.io,gcr.io,quay.io镜像
目录 一.系统环境 二.前言 三.使用现成的镜像代理仓库下载镜像 3.1 使用阿里云镜像仓库 3.2 使用lank8s.cn镜像仓库 3.3 使用中科大镜像 一.系统环境 服务器版本 docker软件 ...