从子面理解
Run:跑
loop:环
所以可以理解为
- 1:运行循环
- 2:跑圈
图形解释
运行循环基本作用
- 保持程序的持续运行
- 处理APP中的各种事件(比如触摸事件;定时器事件;Selector事件)
- 节省CPU的资源,提高程序的性能:也就是该做事的时候做事,不该做事的时候休息。
- ……
APP中的分析
1:为什么我们的APP可以持续的运行?
2:为什么可以让APP可以处理我们的某些事件?
我们从一个最简单的APP入口动手
- 1:APP的入口
main
函数中
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
1:分析main
函数
-
return UIApplicationMain
-这里返回的UIApplicationMain
,也就是主线程,这里面具体他做了一些什么?
其实就是创建了一个主线程的
Runloop
对象,这个Runloop
对象,可以让我们程序持续的运行,也就是说,我们main
这里的大括号,一直都不会退出,大家可以理解为开启了一个死循环。
可以理解为如下:
-
Runloop
存在的情况下
程序有Runloop的情况下
由于
main
函数里面启动了一个Runloop
,所以程序并不会立马退出,可以保存程序的持续的运行。
-
Runloop
不存在的情况下
Runloop不存在的情况下
没有
Runloop
的情况下第三行程序运行就结束了
-
main
函数中
第14行代码
UIAPPlicationMain
函数内部就启动了一个Runloop
- 所有的
UIAPPlicationMain
函数一直没有返回,保持了程序的持续运行。 - 这个默认启动的
Runloop
是跟主线程相关联的。
结论,我们程序的持续运行的原因是因为有了Runloop
的这个对象。
接下来我们研究Runloop
对象。
- 首先iOS中有两套API来访问和使用
Runloop
- Foundation
NSRunloop
- core Foundation
CFRunloopRef
1:NSRunloop
和CFRunloopRef
都是代表着Runloop
对象。
2:NSRunloop
是基于CFRunloopRef
的一层objective-c包装,所以要了解我们的Runloop
,我们需要去多研究CFRunloopRef
层面的API
(http://opensource.apple.com/source/CF/CF-1151.16/ "CFRunloopRef
开源资料")
我们之前是看到了,在程序的主线程中自动启动了一个与之关联的Runloop,那么线程与Runloop
对象的关系到底是怎么样的呢?
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSLog(@"%p %p",[NSRunLoop currentRunLoop],[NSRunLoop mainRunLoop]);
}
- 我们打印
currentRunloop
以及mainRunloop
的内存地址指针
- 可以看得到,他们的内存地址指针是一样的。
我们接下来去子线程里面看一下,一条陌生的子线程和Runloop的关系
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSLog(@"%p %p",[NSRunLoop currentRunLoop],[NSRunLoop mainRunLoop]);
NSThread *thred = [[NSThread alloc]initWithTarget:self selector:@selector(run) object:nil];
[thred start];
}
-(void)run{
//自己创建的子线程,是没有自动创建一个runloop对象的,只有主线程才会默认的创建一个runloop
NSLog(@"%p",[NSRunLoop currentRunLoop]);
}
- 我们创建一条子线程,并且获取了他的一个
currentRunloop
注意:Runloop对象的创建不是使用
alloc
以及init
来创建,而是使用获取currentRunloop
来创建,其实内部就是一个懒加载,在你第一次调用的时候便给你创建Runloop
对象,并且给到你当前的线程.
- 打印结果
我们可以看得到,开启的那条子线程中的
Runloop
对象的地址指针和我们之前在viewDidLoad
中Runloop
的内存地址指针是不一样的。
此时可能会想,是否是一条线程就有一条与之对应且唯一的一个Runloop对象。我们去到CFRunloopRef
的开源代码去分析他。
(http://opensource.apple.com/source/CF/CF-1151.16/ "CFRunloopRef
开源资料")
去到其中CFRunloop
打开源码,我们可以看到这个函数的声明
```CFRunloopRef```内部源码结论
- 主线程的Runloop已经自动创建好了,子线程的Runloop需要主动去创建
- 每条线程都有唯一的一个与之对应Runloop对象
- Runloop在第一次获取时创建,在线程结束时销毁。
网友评论