版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sacrifice123/article/details/51862058
一、什么runloop
从字面意思就是运行循环,他的作用体现在保持程序的持续运行,处理app中的各种事件(比如触摸事件、定时器事件、selector事件),节省cpu资源,提高程序性能:做事的时候做事,没事的时候睡眠。
我们的main函数里就启动了个runloop,所以程序运行起来后并不会马上退出,保持持续运行的状态。
runloop的逻辑处理:
二、runloop与线程
1、每条线程都有唯一的一个与之对应的runloop对象。
2、主线程的runloop已经自动创建好了,子线程的runloop需要主动创建。
3、runloop在第一次获取时创建,在线程结束时销毁。
三、获取runloop对象
lFoundation
[NSRunLoopcurrentRunLoop];// 获得当前线程的RunLoop对象
[NSRunLoopmainRunLoop];// 获得主线程的RunLoop对象
lCoreFoundation
CFRunLoopGetCurrent();// 获得当前线程的RunLoop对象
CFRunLoopGetMain();// 获得主线程的RunLoop对象
三、runloop相关类
1.CFRunLoopRef
2.CFRunLoopModeRef
1)代表runloop的运行模式,一个runloop包含若干个mode,每个mode又包含若干个source/timer/observer,但是每次启动时只能指定其中一个mode,这个mode被称为currentMode,如果需要切换mode,只能退出loop,在重新指定一个mode进入。这样做主要是为了分隔开不同组的Source/Timer/Observer,让其互不影响。
2)系统默认注册了5个Mode
a.
kCFRunLoopDefaultMode
:app默认的mode,通常主线程就是在这个mode下运行的
b.
UITrackingRunLoopMode
:
界面跟踪mode,用于scrollView追踪触摸滑动,保证界面滑动时不受其它mode影响
c. UIInitializationRunLoopMode:在刚启动app时进入的第一个mode,启动完成后就不在使用
d.
GSEventReceiveRunLoopMode
: 接受系统事件的内部 Mode,通常用不到
e.
kCFRunLoopCommonModes
: 这是一个占位用的Mode,不是一种真正的Mode(相当于一个标签,这个标签里可能含有几个mode,表示可以同时运行在几个mode下)
3.CFRunLoopSourceRef
CFRunLoopSourceRef是事件源(输入源)
Source0:非基于Port的
Source1:基于Port的
4.CFRunLoopTimerRef
5.CFRunLoopObserverRef
CFRunLoopObserverRef是观察者,能够监听RunLoop的状态改变
可以监听的时间点如下:
四、runloop的应用举例(线程常驻)
runloop有很多用处,我们规定某个操作在什么模式下进行,下面我们简单看看常驻线程的使用。
我们的线程在使用一次后就会消亡,并且无法重新启动,如果我们希望某个子线程不死,我们可以看如下代码实现:
- (void)viewDidLoad {
[super viewDidLoad];
self.thread = [[NSThread alloc] initWithTarget:self selector:@selector(test) object:nil];
[self.thread start];
}
- (void)test{
NSLog(@"test");
[[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] run];
}
-(void)test1{
NSLog(@"----%@",[NSThread currentThread]);
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
[self performSelector:@selector(test1) onThread:self.thread withObject:nil waitUntilDone:NO];
}
@end
上面的代码重点就在这两行:(这两行代码使得线程不死,执行过一次不会消亡)
[[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] run];