1、
runloop
是线程相关的基础框架的一部分。
2、是一个对象
,这个对象提供一个入口函数。
3、一个runloop
就是一个事件处理的循环
,用来不停的调度工作
以及处理输入事件
。
4、其实内部就是do-while循环
,这个循环内部不断地处理各种任务(比如Source
,Timer
,Observer
)。
5、使用runloop
的目的是让你的线程在有工作的时候忙于工作
,而没工作的时候处于休眠
状态。
重点
:
1、保持程序的持续运行
,
2、处理
app的各种事件
3、节省
CPU资源,提高程序性能
线程
与runloop
是一一对应
的,内部存储是字典
,线程是key,runloop是value- 线程创建的时候,并没有创建runloop 对象,runloop会在
第一次获取的时候自动创建
- 主线程默认开启了runloop,子线程默认没有开启runloop。
- 一个runloop只能在一种模式mode下运行,如果想更换模式,就得从这个runloop退出来。
- runloop 在某个模式下运行,意味着只能在处理这个模式下的source、observe、timer。
// 单独这句代码是不能启动runloop的,需要添加事件(如NSPort、source0、source1、timer)使用observe无效的。
[[NSRunLoop currentRunLoop] run];
CFRunLoopSourceRef
:就是事件源
()输入源
按照官方文档的分类:
1、Port-Based Sources
2、Custom Input Sources
3、Cocoa Perform Selector Sources
按照函数调用栈
,Sources
的分类:
1、Source0
:非基于Port
的(按钮的点击事件
,函数栈可以看)
2、Source1
:基于Port
,通过内核和其他线程通信
,接收
、分发系统事件
source1
接收到的事件最终是要交给source0
的.
CFRunLoopObserver
:是观察者
/* Run Loop Observer Activities */
typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
kCFRunLoopEntry = (1UL << 0), // 即将进入runloop 1
kCFRunLoopBeforeTimers = (1UL << 1), // 即将处理timer 2
kCFRunLoopBeforeSources = (1UL << 2), // 即将处理sources 4
kCFRunLoopBeforeWaiting = (1UL << 5), // 即将进入休眠 32
kCFRunLoopAfterWaiting = (1UL << 6), // 刚从休眠中唤醒 64
kCFRunLoopExit = (1UL << 7), // 即将退出loop 128
kCFRunLoopAllActivities = 0x0FFFFFFFU // 所有状态
};
// 监听当前runloop的所有状态
CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(kCFAllocatorDefault, kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
NSLog(@"%lu",activity);
});
CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);
// 监听完事之后需要释放CoreFoundation框架的对象
CFRelease(observer);
runloop处理逻辑.png
CFRunLoopTimerRef
:是基于时间
的触发器
CFRunLoopTimerRef
基本上说的就是NSTimer
,它受runloop
的mode
的影响
GCD
的定时器是不受runloop的mode影响
GCD
的定时器是什么?
// 这个timer变量需要强引用,不然不会起作用
@property (nonatomic, strong) dispatch_source_t timer;
self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
dispatch_source_set_timer(self.timer, DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
dispatch_source_set_event_handler(self.timer, ^{
NSLog(@"----%@", [NSThread currentThread]);
});
dispatch_resume(self.timer);
//取消定时器
dispatch_cancel(self.timer);
self.timer = nil;
网友评论