RunLoop字面上的意思是,运行循环;
其基本作用:保持程序的持续运行;
处理App中的各种事件(比如:触摸事件、定时器事件、Selector事件)
节省CPU资源,提高程序性能:该做事时做事,该休息时休息
1.main函数中的RunLoop
int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } } 在这个main函数中,UIApplicationMain函数内部就启动了一个RunLoop,所以UIApplicationMain函数一直没有返回,保持了程序的持续运行。这个默认启动的RunLoop是跟主线程相关联的。
NSRunLoop 是基于CFRunLoopRef的一层OC包装,所以了解RunLoop内部结构,需要多研究CFRunLoopRef层面的API。
2.RunLoop与线程的关系
每条线程都有唯一的一个与之对应的RunLoop对象 主线程的RunLoop已经自动创建好了,子线程的RunLoop需要主动创建 RunLoop在第一次获取时创建,在线程结束时销毁获取子线程对应的RunLoop(即,currentRunLoop)该方法本身是懒加载的,如果第一次调用就会创建当前线程对应的RunLoop并保存,以后调用则直接获取
3.RunLoop的获取
#pragma mark - RunLoop - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { //OC语言中的API //01 获取主线程对应的runloop对象 NSRunLoop *mainRunloop = [NSRunLoop mainRunLoop]; //02 获取当前的runloop的对象 NSRunLoop *currentRunloop = [NSRunLoop currentRunLoop]; NSLog(@"%p---%p", mainRunloop, currentRunloop); //C语言的API //01 主运行循环 CFRunLoopRef mainRunloopRef = CFRunLoopGetMain(); //02 当前的运行循环 CFRunLoopRef currentRunloopRef = CFRunLoopGetCurrent(); NSLog(@"%p---%p", mainRunloopRef, currentRunloopRef); //转化 NSLog(@"%p----%p", mainRunloop.getCFRunLoop, mainRunloopRef); }
打印的结果:
2019-09-18 15:31:31.176193+0800 NSCach[60622:1117017] 0x60000184c060---0x60000184c060 2019-09-18 15:31:31.176302+0800 NSCach[60622:1117017] 0x600000050600---0x600000050600 2019-09-18 15:31:31.176362+0800 NSCach[60622:1117017] 0x600000050600----0x600000050600
可以看出,当前的主运行循环和当前运行循环是同一个runloop, 最后一行可以看出,OC获取的runloop与C的runloop可以相互转化。