做你喜欢做的事情,任何时候都不会太迟

0%

对RunLoop的一些看法

RunLoop 介绍

运行循环,在程序运行过程中循环做一些事情,如果没有 Runloop 程序执行完毕就会立即退出,如果有Runloop程序会一直运行,并且时时刻刻在等待用户的输入操作。RunLoop 可以在需要的时候自己跑起来运行,在没有操作的时候就停下来休息。充分节省 CPU 资源,提高程序性能。

1、RunLoop 的基本作用

  • 保持程序的持续运行
  • 处理 App 中的各种事件(比如触摸事件、定时器事件等)
  • 节省 CPU 资源,提高程序性能:该做事时做事,该休息时休息

2、RunLoop 对象

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

  • Foundation:NSRunLoop

  • Core Foundation:CFRunLoopRef

  • NSRunLoop 和 CFRunLoopRef 都代表着 RunLoop 对象

  • NSRunLoop 是基于 CFRunLoopRef 的一层 OC 包装

  • CFRunLoopRef 是开源的


3、RunLoop 与线程

  • 每条线程都有唯一的一个与之对应的 RunLoop 对象
  • RunLoop 保存在一个全局的 Dictionary 里,线程作为 key,RunLoop 作为 value
  • 线程刚创建时并没有 RunLoop 对象,RunLoop 会在第一次获取它时创建
  • RunLoop 会在线程结束时销毁
  • 主线程的 RunLoop 已经自动获取(创建),子线程默认没有开启 RunLoop

4、获取RunLoop对象

1
2
3
4
5
6
7
8
9
10
11
// Foundation
// 获得当前线程的 RunLoop 对象
[NSRunLoop currentRunLoop];
// 获得主线程的 RunLoop 对象
[NSRunLoop mainRunLoop];

// Core Foundation
// 获得当前线程的 RunLoop 对象
CFRunLoopGetCurrent();
// 获得主线程的 RunLoop 对象
CFRunLoopGetMain();

5、RunLoop 相关的类

Core Foundation 中关于 RunLoop 的5个类

  • CFRunLoopRef
1
2
3
4
5
6
7
8
typedef struct __CFRunLoop * CFRunLoopRef
struct __CFRunLoop {
pthread_t _pthread;
CFMutableSetRef _commonModes;
CFMutableSetRef _commonModeItems;
CFRunLoopModeRef _currentMode;
CFMutableSetRef _modes;
};
  • CFRunLoopModeRef
1
2
3
4
5
6
7
8
typedef struct __CFRunLoopMode * CFRunLoopModeRef
struct __CFRunLoopMode {
CFStringRef _name;
CFMutableSetRef _sources0;
CFMutableSetRef _sources1;
CFMutableArrayRef _observers;
CFMutableArrayRef _timers;
};
  • CFRunLoopSourceRef
  • CFRunLoopTimerRef
  • CFRunLoopObserverRef

RunLoop


6、CFRunLoopModeRef

  • CFRunLoopModeRef 代表 RunLoop 的运行模式

一个 RunLoop 包含若干个 Mode,每个 Mode 又包含若干个 Source0/Source1/Timer/Observer

  • RunLoop 启动时只能选择其中一个 Mode,作为 currentMode
  • 如果需要切换 Mode,只能退出当前 Loop,再重新选择一个 Mode 进入
  • 不同组的 Source0/Source1/Timer/Observer 能分隔开来,互不影响
  • 如果 Mode 里没有任何 Source0/Source1/Timer/Observer,RunLoop 会立马退出
  • 系统默认注册了 5 个 Mode
  • kCFRunLoopDefaultMode(NSDefaultRunLoopMode):App 的默认 Mode,通常主线程是在这个 Mode 下运行的
  • UITrackingRunLoopMode:界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他 Mode 影响
  • UIInitializationRunLoopMode: 在刚启动 App 时第进入的第一个 Mode,启动完成后就不再使用
  • GSEventReceiveRunLoopMode: 接受系统事件的内部 Mode,通常用不到
  • kCFRunLoopCommonModes: 这是一个占位的 Mode,没有实际作用

7、RunLoop的运行逻辑

  • Source0

    • 触摸事件处理
    • performSelector:onThread:
  • Source1

    • 基于 Port 的线程间通信
    • 系统事件捕捉
  • Timers

    • NSTimer
    • performSelector:withObject:afterDelay:
  • Observers

    • 用于监听 RunLoop 的状态
    • UI刷新(BeforeWaiting)
    • Autorelease pool(BeforeWaiting)

RunLoop_Logic

7、RunLoop在实际开中的应用

  • 控制线程生命周期(线程保活)
  • 解决NSTimer在滑动时停止工作的问题
  • 监控应用卡顿
  • 性能优化