1)什么是 Runloop ?

1、字面上是运行循环,内部就是 do-while 循环,在这个循环内不断地处理各种任务。

2、一个线程对应一个 Runloop ,主线程的 RunLoop 默认是开启的。子线程的 RunLoop 需手动开启。

3、RunLoop 只能对应选择一个 Model 启动,如果当期的 Model 中没有任何 Source(Sources0,Sources1)、Timmer,那么就直接退出 RunLoop。

4、基本作用就是保持程序的持续运行,处理 APP 中的各种事件、通过 RunLoop ,有事执行,没事休眠,可以节省 CPU 资源,提高程序性能。

2)iOS 中有2套 API 访问和使用 RunLoop

在 Fundation 框架下:NSRunLoop

在Core Fundation 下:CFRunLoopRef

比较:

1、NSRunLoop 和 CFRunLoopRef 都代表 RunLoop 对象

2、NSRunLoop 是基于 CFRunLoopRef 的一层 OC 封装。

3)RunLoop 与 线程:

1、每条线程都有唯一对应的 RunLoop 对象;

2、主线程的 RunLoop 已经自动创建好了,子线程的 RunLoop 需要主动创建

3、RunLoop 在第一次获取时创建,在线程结束时销毁。

4)获取 RunLoop 对象:

Fundation 框架:

[NSRunLoop currentRunLoop];//获取当前线程的 RunLoop 对象

[NSRunLoop mainRunLoop];//获取主线程的 RunLoop 对象

Core Fundation 框架:

CFRunLoopGetCurrent();  // 获取当前线程的 RunLoop 对象

CFRunLoopGetMain(); //获取主线程的 RunLoop 对象

5)RunLoop 处理逻辑:

1、通知 Observer:即将进入 Loop

2、通知 Observer:即将处理 Timer

3、通知 Observer:将要处理 Source0

4、处理 Source0

5、如果有 Source0,跳到步骤 9

6、通知 Observer:线程即将休眠

7、休眠,等待唤醒:

1> Source0(port)

2> timer 启动

3> RunLoop 设置的 timer 已经超时

4> RunLoop 被外部手动唤醒

8、通知 Observer:线程将被唤醒

9、处理未处理的时间:

1> 如果用户定义的定时器启动,处理定时器事件并重启 RunLoop。进入步骤 2

2> 如果输入源启动,传递相应的消息

3> 如果 RunLoop 被显式唤醒而且时间还没超时,重启 RunLoop,进入步骤 2

10、通知 Observer:即将推出 Loop

6)RunLoop 应用场景:

NSTimer

ImageView 显示

PerformSelector

常驻线程

自动释放池

应用场景:

1> 开启一个常驻线程(让一个子线程不进入消亡状态,等待其他线程发来消息,处理其他事件)

2> 在子线程中开启一个定时器

3> 在子线程中进行一些长期监控

4> 可以控制定时器在特定模式下执行

5> 可以让某些事件(行为、任务)在特定模式下执行

6> 可以添加 Observer 监听 RunLoop 的状态,比如监听点击事件的处理(在所有点击事件之前做一些事情)

7)NSRunLoop 的实现机制,及在多线程中如何使用

程序创建子线程的时候,才需要手动启动 RunLoop,主线程的 RunLoop 默认开启

在多线程中,你需要判断是否需要 RunLoop,如果需要,那么你负责配置 RunLoop 并启动,你不需要在任何时候都去启动 RunLoop。例如:使用线程去处理一个预定好的耗时极长的任务时,你就可以无需启动 RunLoop。RunLoop 只有在和线程交互时才需要。

8)RunLoop 的 Model 的作用:

mode 主要用来指定事件在运行循环中的优先级的。

• NSDefaultRunLoopMode (kCFRunLoopDefaultMode):默认,空闲状态

• UITrackingRunLoopMode ScrollView:         ScrollView 滑动时会切换到该Mode

• UIInitializationRunLoopMode run loop:       RunLoop 启动时,会切换到该 mode

如果我们把一个 NSTimer 对象以 NSDefaultRunLoopMode(KCFRunLoopDefaultMOde) 添加到主运行循环中的时候,ScrollView滚动过程中会因为 Mode 的切换,而导致 NSTimer 不在被调度。当我们滚动的时候,也不希望调度,那么就应该使用默认模式。但是,虚妄在滚动时,定时器也要回调,那就应该使用 commonMode。

如果想要销毁 Timer ,则必须先将 Timer 置为失效,否则 Timer 就一直占用内存而不会释放。造成逻辑上的内存泄露。该泄露不会使用 Xcode 工具 Instrument 检测出来、另外对于要求必须销毁的 Timer 的逻辑处理,未将 Timer 置为失效,若每次都创建一次,则之前的不能得到释放,则会同时存在多个 Timer 的实例在内存中。

在 Timer 不需要时,一定要调用 invalidate 方法使定时器失效,否则得不到释放。

如果要 Cell 滚动过程中定时器正常回调,UI 正常刷新,那么要将 Timer 放入 CommonMode 下,因为 NSDefaultRunLoopMode 只有在空闲状态下才会回调。

UIScrollView 的滚动导致 NSTimer 失效:

1、更改 mode 为 NSRunLoopCommonModes(无论 RunLoop 运行在哪个 Mode都能运行)

2、切换到主线程来更新 UI 界面刷新

// 将timer添加到 NSDefaultRunLoopMode 中

[NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(timerTick:) userInfo:nil repeats:YES];

//  然后再添加到 NSRunLoopCommonModes里

NSTimer *timer = [NSTimer timerWithTimeInterval:2 target:self selector:@selector(timerTick:) userInfo:nil repeats:YES];

[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

iOS 开发之 RunLoop 详解的更多相关文章

  1. IOS开发之UINavigationController详解

    UINavigationController是IOS编程中比较常用的一种容器view controller,很多系统的控件(如UIImagePickerViewController)以及很多有名的AP ...

  2. ios开发之 NSObject详解

    NSObject是大部分Objective-C类继承体系的根类.这个类遵循NSObject协议,提供了一些通用的方法,对象通过继承NSObject,可以从其中继承访问运行时的接口,并让对象具备Obje ...

  3. iOS开发之Quartz2D详解

    1. 什么是Quartz2D? Quartz 2D是一个二维绘图引擎,同时支持iOS和Mac系统 Quartz 2D能完成的工作 绘制图形 : 线条\三角形\矩形\圆\弧等 绘制文字 绘制\生成图片( ...

  4. iOS开发之SDWebImage详解

    介绍 github地址: https://github.com/rs/SDWebImage 简介 一个异步图片下载及缓存的库 特性: 一个扩展UIImageView分类的库,支持加载网络图片并缓存图片 ...

  5. Android开发之InstanceState详解

    Android开发之InstanceState详解   本文介绍Android中关于Activity的两个神秘方法:onSaveInstanceState() 和 onRestoreInstanceS ...

  6. Android开发之InstanceState详解(转)---利用其保存Activity状态

    Android开发之InstanceState详解   本文介绍Android中关于Activity的两个神秘方法:onSaveInstanceState() 和 onRestoreInstanceS ...

  7. Android开发之MdiaPlayer详解

    Android开发之MdiaPlayer详解 MediaPlayer类可用于控制音频/视频文件或流的播放,我曾在<Android开发之基于Service的音乐播放器>一文中介绍过它的使用. ...

  8. 李洪强iOS开发之RunLoop的原理和核心机制

    李洪强iOS开发之RunLoop的原理和核心机制 搞iOS之后一直没有深入研究过RunLoop,非常的惭愧.刚好前一阵子负责性能优化项目,需要利用RunLoop做性能优化和性能检测,趁着这个机会深入研 ...

  9. iOS开发之Runloop(转)

    Objective-C之run loop详解 作者:wangzz 原文地址:http://blog.csdn.net/wzzvictory/article/details/9237973 转载请注明出 ...

随机推荐

  1. 【转自】自定义InputFormat、OutputFormat

    转自:http://www.cnblogs.com/xiaolong1032/p/4529534.html 一:自定义实现InputFormat *数据源来自于内存*1.InputFormat是用于处 ...

  2. linux nmon安装

    系统版本红帽7.7: [root@hostuser1 nmon_permon]# cat /etc/redhat-release CentOS Linux release 7.7.1908 (Core ...

  3. office2013激活工具,可以激活新版本office 2013

    耽误一上午没激活成功,最后还是找到了激活文件KMSpico v9.0.6.zip 链接:https://pan.baidu.com/s/1WEyJm8kVnqDONRJRHTRQiQ 提取码:4h45 ...

  4. vue 对象数组中,相邻的且相同类型和内容的数据合并,重组新的数组对象

    在项目中,有时候会遇到一些需求,比如行程安排,或者考勤状态.后台返回的获取是这一周的每一天的状态,但是我们前端需求显示就是要把相邻的且状态相同的数据进行合并,所以我们就要重新组合返回的数据.如下所示: ...

  5. ElementUI+Vue在使用el-dialog时,如何做到在弹出dialog时,外部呈锁定状态,而不是点击外部导致dialog直接关闭。

    ElementUI+Vue在使用el-dialog时,如何做到在弹出dialog时,外部呈锁定状态,而不是点击外部导致dialog直接关闭. 问题描述 今天,在做Element+Vue项目时发现:Di ...

  6. P &R 12

    Floorplan包含: IO floorplan: 涉及板级设计.封装设计的交互,接口协议(timing相关),对一些高速接口需要做特殊考虑(如信号完整性等). Power plan:芯片的电源和低 ...

  7. API接收数据反序列化失败问题查找

    C# API接收到数据后,反序列化后直接返回null,而不会给出错误提示,所以不好排查错误. 通过在api中直接进行反序列化,能够得到错误明细: 没有报错的时候,request会直接为null,不会报 ...

  8. 从csv文件里取数据作为请求参数,和把返回数据放到一个csv文件

    本来想把登陆后的token放到数组里,下一个参数用,但是貌似不支持数组,暂时先这样用了,并不麻烦,还很方便. 1.添加线程组等必要的东东后,添加csv配置器 2.进行设置 说明:csv文件设置不能读取 ...

  9. finalize()

    本文介绍的是Java里一个内建的概念,Finalizer.你可能对它对数家珍,但也可能从未听闻过,这得看你有没有花时间完整地看过一遍java.lang.Object类了.在java.lang.Obje ...

  10. jmeter循环读取数据库中的数据

    1,添加一个jdbc请求 2,添加一个循环控制器,循环的次数为sql返回的记录数${var_#} 3,添加一个计数器(用来做变量拼接) 4,拼接变量,往目标接口发请求 最后脚本的构造如下: