--------------------RunLoop--------------------
什么是RunLoop
运行循环,在程序运行过程中循环做一些事情
RunLoopde 应用范畴
定时器(Timer)、PerformSelector
GCD Async Main Queue
事件响应、手势识别、界面刷新
网络请求
AutoreleasePool
RunLoop与线程
- 每条线程都有唯一的一个与之对应的RunLoop对象
- RunLoop保存在一个全局的Dictionary里,线程作为key,RunLoop作为value
- 线程刚创建时并没有RunLoop对象,RunLoop会在第一次获取它时创建
- RunLoop会在线程结束时销毁
- 主线程的RunLoop已经自动获取(创建),子线程默认没有开启RunLoop
获得RunLoop对象
Foundation
[NSRunLoop currentRunLoop]; // 获得当前线程的RunLoop对象
[NSRunLoop mainRunLoop]; // 获得主线程的RunLoop对象
Core Foundation
CFRunLoopGetCurrent(); // 获得当前线程的RunLoop对象
CFRunLoopGetMain(); // 获得主线程的RunLoop对象
RunLoop相关的5个类:
CFRunLoopRef
CFRunLoopModeRef
CFRunLoopSourceRef
CFRunLoopTimerRef
CFRunLoopObserverRef
CFRunLoop和 CFRunLoopMode
// CFRunLoop.h
typedef struct __CFRunLoop * CFRunLoopRef;
// CFRunLoop.c
struct __CFRunLoop {
pthread_t _pthread; // 与线程一一对应
CFMutableSetRef _commonModes;
CFMutableSetRef _commonModeItems;
CFRunLoopModeRef _currentMode;
CFMutableSetRef _modes;
...
};
// CFRunLoop.h
typedef struct __CFRunLoopMode *CFRunLoopModeRef;
// CFRunLoop.c
struct __CFRunLoopMode {
CFStringRef _name; // mode 类型,如:NSDefaultRunLoopMode
CFMutableSetRef _sources0; // CFRunLoopSourceRef
CFMutableSetRef _sources1; // CFRunLoopSourceRef
CFMutableArrayRef _observers; // CFRunLoopObserverRef
CFMutableArrayRef _timers; // CFRunLoopTimerRef
...
};
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会立马退出
常见的两种mode:
- kCFRunLoopDefaultMode(NSDefaultRunLoopMode):App的默认Mode,通常主线程是在这个Mode下运行
- UITrackingRunLoopMode:界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他 Mode 影响
CFRunLoopObserverRef
/* Run Loop Observer Activities */
typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
kCFRunLoopEntry = (1UL << 0), // 即将进入 RunLoop
kCFRunLoopBeforeTimers = (1UL << 1), // 即将处理 Timers
kCFRunLoopBeforeSources = (1UL << 2), // 即将处理 Sources
kCFRunLoopBeforeWaiting = (1UL << 5), // 即将进入休眠
kCFRunLoopAfterWaiting = (1UL << 6), // 刚从休眠中唤醒
kCFRunLoopExit = (1UL << 7), // 即将退出 RunLoop
kCFRunLoopAllActivities = 0x0FFFFFFFU // 表示以上所有状态
};
添加RunLoop的监听:
// 创建Observer
CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(kCFAllocatorDefault, kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
switch (activity) {
case kCFRunLoopEntry: {
NSLog(@"kCFRunLoopEntry");
break;
}
case kCFRunLoopBeforeTimers: {
NSLog(@"kCFRunLoopEntry");
} break;
case kCFRunLoopBeforeSources: {
NSLog(@"kCFRunLoopEntry");
} break;
case kCFRunLoopBeforeWaiting: {
NSLog(@"kCFRunLoopEntry");
} break;
case kCFRunLoopAfterWaiting: {
NSLog(@"kCFRunLoopEntry");
} break;
case kCFRunLoopExit: {
NSLog(@"kCFRunLoopExit");
break;
}
default:
break;
}
});
// 添加Observer到RunLoop中
CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopCommonModes);
// 释放
CFRelease(observer);
RunLoop的运行逻辑
先上一张老图

-
Source0
触摸事件处理
performSelector:onThread: -
Source1
基于Port的线程间通信
系统事件捕捉 -
Timers
NSTimer
performSelector:withObject:afterDelay: -
Observers
用于监听RunLoop的状态
UI刷新(BeforeWaiting)
Autorelease pool(BeforeWaiting)
过程:

网友评论