1、runloop概念
字面意思:运行循环,其内部实现实际是do-while循环实现的
2、作用
保证程序的正常运行,处理APP的各种事件(滑动、定时器、selector),节省cpu资源,提高程序性能。
如果程序中没有runloop,则程序运行完,立马关闭退出。
而有runloop则程序相当于一个死循环,保证程序的正常运行。
int main(int argc ,char * argv[]){
do{
nslog(@"execute main function");
}while(1);
return 0;
}
OC代码中,在程序入口处,实际上是再UIApplicationMain函数内部中启动了一个runloop,所以UIApplicationMain函数中就一直没有返回值
,保证了程序的持续运行。
注意:默认启动的runloop是跟主线程相关的,处理主线程相关的事件。
3、runoop对象
ios中有两套API来访问和使用runloop
foundation框架下的NSRunloop 另一个是CORE Foundation框架下的 CFRunloopRef,其中NSRunloop是基于CFRunloopref的。
4、runloop 与线程
1》每条线程都有唯一一个与之对应的runloop
2》主线程的runloop随着程序以自动创建好,但是子线程的runloop需要手动创建。
3》获取住线程的runloop方法为:[nsrunloop mainrunloop];
4》创建子线程的runloop方法:[nsrunloop currentrunloop];
注意:苹果不允许创建runloop,只能通过上面两种方式获取runloop
5、runloop相关类
cfrunloopmoderef
cfrunloopmoderef代表runloop的运行模式
一个runloop可以办函若干个model,每个mode包含若干个source/timer/observer
每次启动runloop,只能制定其中的一个mode,这个mode为currentmode
如果需要切换mode,需呀退出runloop,再重新指定一个mode进入,这样做的原因是为了分离不同组的source/timer/
observer,让其互不影响
KCFRunloopDefaultMode :app的默认mode,通常主线程就是再该mode下运行。
UITrackRunLoopRefMode: 界面跟踪mode,用于scrollview追踪触摸滑动,保证界面滑动时,不受其他mode影响。
UIInitializationRunLoopMode:再刚启动app的时候进入的第一个mode,启动玩后不再使用
GSEventRecieveRunLoopMode:接受系统事件的内部Mode,通常情况下不用
KCFRunloopCommonModes:这是一个占位mode,不是真正的mode,有这个标记模式的有default / track
cfrunloopsourceref
事件源,也可称为输入源
官方文档:
1》port-based souces 从其他线程或内核发出的
2》custom input sources 自定义的
3》 cocoa perform selector sources
函数调用栈分类:
1》sources0 非基于port
2》sources1 基于port ,通过其他线程或者内核通信,接收、分发系统事件
cfrunlooptimerref
基于时间的触发器,NSTimer
cfloopobserverref
- (void)observer{
// 创建一个监听者
// CFRunLoopObserverCreate(<#CFAllocatorRef allocator#>, <#CFOptionFlags activities#>, <#Boolean repeats#>, <#CFIndex order#>, <#CFRunLoopObserverCallBack callout#>, <#CFRunLoopObserverContext *context#>)
// 使用下面这种方法
/**
第一个参数:(<#CFAllocatorRef allocator#>)分配存储空间
第二个参数:(<#CFOptionFlags activities#>)要监听的状态(kCFRunLoopAllActivities)所有的状态
第三个参数:(<#Boolean repeats#>)是否持续监听
第四个参数:(<#CFIndex order#>)优先级
第五个参数:回调
*/
CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
switch (activity) {
case kCFRunLoopEntry:
NSLog(@"即将进入runloop");
break;
case kCFRunLoopBeforeTimers:
NSLog(@"即将处理 Timer");
break;
case kCFRunLoopBeforeSources:
NSLog(@"即将处理 Sources");
break;
case kCFRunLoopBeforeWaiting:
NSLog(@"即将进入休眠");
break;
case kCFRunLoopAfterWaiting:
NSLog(@"从休眠中唤醒loop");
break;
case kCFRunLoopExit:
NSLog(@"即将退出runloop");
break;
default:
break;
}
});
// 给runloop添加监听者
/**
第一个参数:(<#CFRunLoopRef rl#>)要监听哪个runloop
第二个参数:(<#CFRunLoopObserverRef observer#>)监听者
第三个参数:(<#CFStringRef mode#>)要监听runloop在哪种运行模式下的状态
*/
CFRunLoopAddObserver(CFRunLoopGetCurrent(),observer,kCFRunLoopDefaultMode);
/// 这里可以自己写一个NSTimer实验一下
// 释放runloop
CFRelease(observer);
}
#凡是带有Create,Copy,Retain等字眼的函数,创建出来的对象,都要在最后做一次release操作
runloop逻辑处理: