一.RunLoop的基本概念
RunLoop是oc底层的一个机制,是运行循环,死循环。当应用程序需要的时候跑起来,不需要的时候处于休眠状态,这种特性可以充分提高CPU资源,提高程序的性能。
NSRunLoop三种模式:
- NSRunLoopCommonModes:占位模式(并不是runloop的一种模式) 无论是否操作UI都处理timer事件
- NSDefaultRunLoopMode:默认模式 当不操作UI的时候才 苹果建议处理timer事件 网络事件
- UITrackingRunLoopMode:ui 模式 当操作ui的时候才处理timer事件 苹果建议处理ui事件
二.RunLoop的作用
RunLoop常常和线程结合在一起讨论
1.保证线程不退出(RunLoop一旦启动 线程就不会退出)
一般来讲,一个线程一次只能执行一个任务,执行完成后线程就会退出。但是有时候我们需要线程能够一直“待命”随时处理事件而不退出,这就需要一个机制来完成这样的任务。
2.负责监听所有的事件 iOS中的触摸/时钟/网络事件
比如说时钟事件 创建timer 有两种方式 一种是
(1). 添加到默认模式 将RunLoop封装起来
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
(2).另一种是创建timer后手动开启runloop
_finished = NO;
_tasks = [NSMutableArray array];
//创建的子线程
NSThread *thread = [[NSThread alloc] initWithBlock:^{
NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
//将timer加到当前runloop中 但是执行一次后 线程被释放
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
//让当前线程的runloop跑起来 监听事件 保证线程不被释放 如果没有这段代码 则执行一次后线程会被释放 一条线程要想保住 必须让runloop启动 是一个死循环
[[NSRunLoop currentRunLoop] run];
while (!_finished) {
//让runloop跑0.00001秒 跑起来有事情处理事情 没事情就沉睡
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.0001]];
}
//有[[NSRunLoop currentRunLoop] run];则不会打印
NSLog(@"我来了");
}];
//启动线程
[thread start];
//强引用使thread对象不会被释放 保住的是thread(一个oc对象) 但没有保住线程 线程是由CPU来调用的和oc对象没有丝毫关系 oc对象只是提供了一个接口来操作线程 线程的释放与oc没关系 只能runloop来保住线程
self.thread = thread;
在这里如果不手动开启runloop 即[[NSRunLoop currentRunLoop] run]则线程执行一次后就直接被释放 如果声明一个强引用只能使thread对象不会被释放 保住的是thread(一个oc对象) 但没有保住线程 线程是由CPU来调用的和oc对象没有丝毫关系 oc对象只是提供了一个接口来操作线程 线程的释放与oc没关系 只能runloop来保住线程。
3.负责绘制UI
三.RunLoop与线程的关系
RunLoop,最重要的作用,也就是用来管理线程的。可以说,没有线程,也就没有RunLoop的存在必要。
主线程和子线程:
1.没有任何分别
2.只不过主线程的RunLoop是由操作系统来开启的 子线程的RunLoop是由开发者手动开启的。
其实在我们每次建立项目的时候,就已经使用上了RunLoop。
在程序的启动入口main函数中有这样一段熟悉的代码:
参数解释:
argc, argv:则是由操作系统传给app的所以这两个参数无需管理
nil:默认是字符串@“UIApplication” 当然也可以自定义一个类继承UIApplication
NSStringFromClass([AppDelegate class]:字符串
应用程序的main函数是由操作系统启动的,操作系统开启了一条主线程(对应用程序来说是主线程 但对于操作系统来说是子线程)此内部已经开启了RunLoop死循环,所以app的主线程是常驻线程,在自动释放池中不会被释放从而保证应用程序不会退出。
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
网友评论