美文网首页iOS知识点
iOS RunLoop进阶之一----CFRunLoop延迟加载

iOS RunLoop进阶之一----CFRunLoop延迟加载

作者: 游龙飞雪 | 来源:发表于2018-03-22 12:44 被阅读176次
    对于列表,流畅性是衡量性能的一个重要指标。如果cell中要加载多张大图,比如每张图超过2~3M,那么在滑动的时候系统一边要处理滑动,一边又要渲染这么大的图片多张,肯定会卡,这是毫无疑问的。

那么这种卡顿现象是怎么造成的呢?这不是异步加载的问题,通俗一点说是主线程更新UI的问题。

我们知道每个线程都有一个RunLoop,主线程的RunLoop是系统默认开启的。而RunLoop在不处理事件的时候就会休眠。那就引出一个概念,我个人称之为 RunLoop的“工作周期”(类比控制器的生命周期),各种状态如下:

/* Run Loop Observer Activities */
typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
kCFRunLoopEntry = (1UL << 0),
kCFRunLoopBeforeTimers = (1UL << 1),
kCFRunLoopBeforeSources = (1UL << 2),
kCFRunLoopBeforeWaiting = (1UL << 5), //即将休眠
kCFRunLoopAfterWaiting = (1UL << 6),
kCFRunLoopExit = (1UL << 7),
kCFRunLoopAllActivities = 0x0FFFFFFFU
};

这里有个状态是 kCFRunLoopBeforeWaiting(即将休眠),我们设置一个 timer 每隔 0.01s 响应一次,并添加到 RunLoop 的默认模式中,那么时钟在列表滑动的UI事件结束之后才会有效,对应本例中就是列表滑动结束之后时钟跳动一次即将结束的时候,这个时候再让 RunLoop 来做加载图片,就不会跟滑动冲突了,也就不会造成列表卡顿了。(注意:列表滑动的时候是不加载图片的。)

这就是本文讨论的“延迟加载图片”。

怎么知道什么时候是 kCFRunLoopBeforeWaiting 状态呢?在CFRunLoop中,有个监听者,我们创建这个监听者通过函数回调(C语言中回调一般都是函数指针)来监听状态处理任务。
代码如下:

image.png

这里理一下思路:
背景环境:控制器中有一个tableView,有几百个cell,每个cell中有3个imageView,每个imageView要加载 3M 的大图片。
在cellForRow的数据源方法中不直接给cell.imageView设置图片,而是利用runloop的 kCFRunLoopBeforeWaiting 状态的回调函数执行设置图片的任务。

  1. 在viewDidLoad中添加监听者监听runloop的状态;

  2. 设置时钟,添加到runloop的 “默认模式” 执行,一定要默认模式才是本文思路的关键;

  3. 设置一个属性--存放任务的数组tasks,在cellForRow中,把给imageView设置图片的代码作为任务用block包装,将这个block任务存放到tasks数组中;
    伪代码如下:


    image.png
  4. 回调函数Callback 中(回调函数是C语言的函数),从tasks数组中取出任务并执行,随即更新tasks。


    image.png

这样,就达到了延迟执行的效果。


需要的注意的是,这样子会造成内存疯长,处理方法是在cellForRow的数据源方法中,移除cell.contentView中的子控件,这里其实就是3个imageView,在 添加任务的block任务中,再给 contentView 动态添加 3 个 imageView,用CPU的性能换来内存空间,就不会使内存疯长了。

相关文章

  • iOS RunLoop进阶之一----CFRunLoop延迟加载

    那么这种卡顿现象是怎么造成的呢?这不是异步加载的问题,通俗一点说是主线程更新UI的问题。 我们知道每个线程都有一个...

  • RunLoop

    RunLoop 原理 RunLoop 这个对象,在 iOS 里由 CFRunLoop 实现。简单来说,RunLoo...

  • Runloop总结

    深入理解RunLoopMac&iOS之多线程CFRunLoop运用 RunLoop 的概念 runloop是一个对...

  • iOS---RunLoop深度剖析

    RunLoop 前言 RunLoop是iOS/OS开发中比较基础的一个概念,在苹果开发中用在事件处理,延迟加载,屏...

  • 看 CFRunLoop源码深入理解 RunLoop

    原文地址Runloop是 iOS 中的基础概念,这篇文章将通过CFRunLoop源码来看RunLoop的概念及底层...

  • Runloop相关探索

    Runloop 和 线程 在CFRunloop中已经说明了一个线程及其runloop的对应关系,现在以iOS中NS...

  • RunLoop入门提高

    RunLoop是iOS和OSX开发中非常基础的一个概念.首先从CFRunLoop的源码入手,介绍RunLoop的概...

  • Runloop 详解

    Runloop 详解 参考链接: 深入理解RunLoop CFRunLoop 概念 runloop :是管理和处理...

  • iOS - 深入理解 RunLoop

    序言 RunLoop 是 iOS 和 OSX 开发中非常基础的一个概念,该文章将从CFRunLoop 的源码入手,...

  • 深入理解 Apple RunLoop

    RunLoop 是 iOS 和 OS X 开发中非常基础的一个概念,本文将从 CFRunLoop 的源码入手,介绍...

网友评论

    本文标题:iOS RunLoop进阶之一----CFRunLoop延迟加载

    本文链接:https://www.haomeiwen.com/subject/xfioqftx.html