概要
下面两篇文章:
都是在 iOS 平台上如何利用 RunLoop
的特性实现常驻线程.
可能你看到本篇文章的标题 移除常驻线程
, 有点不理解甚至觉得作者是不是有点神经病, 都已经需要常驻线程了, 为什么还要去退出呢?
实际应用场景中的确几乎遇不到这种情况, 所以, 本篇只是从技术的角度给大家分享 RunLoop
其他的一些知识点.
且耐住性子往下看…
为了不让大家误解, 统一一下相关的词汇和语境.
- 输入源, 包括 source 和 timer.
- 退出 RunLoop 指的是在常驻线程的方法中立即返回.
- 这里的 RunLoop 指的是子线程中的 RunLoop 不是主线程中的.
- 结合之前介绍常驻线程的文章来看现在的文章, 不然不好理解.
运行 RunLoop 的方法
这里有三种方式开启运行 RunLoop, 分别如下:
1 | - (void)run; |
- run 方法
看一下 API 文档如何解释 run
方法的:
1 | Puts the receiver into a permanent loop, |
大致意思讲的是, 在没有任何输入源的情况下, run
方法会立即执行后退出, 不会保持线程的持久性, 换句话说, 在有输入源的情况下, 该方法会进入一个无限循环当中. 本质上, 在 NSDefaultRunLoopMode
模式下, 该方法是反复调用 runMode:beforeDate:
方法的.
在之前文章实现常驻线程的代码中, 我们使用了 run
方法来开启运行 RunLoop.
可以看出, 我们之前实现的常驻线程使用 run
方法是无法退出常驻线程的.
- *runUntilDate:(NSDate )limitDate 方法
该方法 API 释义:
1 | Runs the loop until the specified date, |
保证有输入源的情况下该方法启动的 RunLoop 可以在指定的日期内一直运行不会返回. 换句话说, 日期只要已到该方法就会立即退出 RunLoop.
示例代码:
1 | //等同于 run, 可保证一直运行 |
- **runMode:(NSString )mode beforeDate:(NSDate )limitDate 方法
该方法有两个参数 mode
和 limitDate
, mode
就是 RunLoop 的运行模式, limitDate
就是上面方法一样的释义即在指定的日期内.
1 | Runs the loop once, blocking for input in the specified mode until a given date. |
可以这么理解, 该方法开启的 RunLoop 处理完之后会立即返回(once), 如果在指定日期内事件还没处理, 在该日期后会立即返回.
换句话说, 如果指定的日期是当前的, 该方法执行后 RunLoop 会立即退出.
示例代码:
1 | //立即返回 |
这三个方法, 总结一下大概如下:
- 这三个方法在没有任何输入源情况下会都立即返回(退出 RunLoop), 不会等待.
run
可保证 RunLoop 在有输入源的情况下一直运行.runUntilDate
可以通过设置超时时间来退出 RunLoop. 超时时间一过就会立即退出 RunLoop.- 使用
runMode
方式启动的 RunLoop 会在处理完事件后或者超时后, 立即返回. 即可以通过设置超时时间或者使用CFRunLoopStop
方法来退出 RunLoop.
移除常驻线程
先看一下, 在子线程执行的方法中如何实现的. 示例代码如下:
1 | - (void)asyncRun { |
结合上面讲解的原理, 这里选择使用 runMode
方法来开启运行 RunLoop. 大家也可以自由发挥使用其他的方法.
注意: stopLoopRunning
是定义的一个属性.
移除的示例代码如下:
1 | - (void)viewDidDisappear:(BOOL)animated { |
离开页面后, 可以发现 NSLog(@"--- asyncRun ----");
停止了打印, 并且当前的 Controller 也 dealloc 了.
扫码关注,你我就各多一个朋友~