理解 OC 中 RunLoop
什么是RunLoop?
可以简单理解为,让程序保持运行的一个while循环,这个循环内监听各种事件(如触摸事件、performSelector、定时器NSTimer等),没有事件的时候睡眠,从而有效的利用CPU(只有在有事件的时候才用CPU,没事件的时候睡眠)
不管RunLoop有多复杂,其本质就是上面所说的:一个循环,有事件的时候处理事件,无事件的时候休眠(这里的睡眠是指用户态切换到内核态,这样的休眠线程是被挂起的,不会再占用cpu资源)。
RumLoop与线程有如下关系:
- 一个线程只有一个RunLoop对象
- 主线程的RunLoop默认已经创建好了,而子线程的需要手动创建。
- RunLoop在第一次获取时创建,在线程结束时销毁。
我们验证一下,在main函数返回之前,打印一下:
int main(int argc, char *argv[])
{
NSString *appDelegateClassName;
@autoreleasepool {
// Setup code that might create autoreleased objects goes here.
appDelegateClassName = NSStringFromClass([AppDelegate class]);
}
int ret = UIApplicationMain(argc, argv, nil, appDelegateClassName);
NSLog(@"after ret");
return ret;
}
结果没有打印,这说明主进程已经进入了一个RunLoop主了,主进程不结束,就跳不出RunLoop,也就执行不了之后的打印。
我们打印一下主线程的RunLoop试试:
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"%@", [NSRunLoop currentRunLoop]);
}
// 打印结果(只取关键信息):
// CFRunLoop 0x600001704700
// current mode = kCFRunLoopDefaultMode,
这说明主线程在一个RunLoop中,并且当前的运行模式是kCFRunLoopDefaultMode
这样感觉RunLoop很简单,但它又很复杂,因为要考虑的因素有很多,比如各种事件的处理顺序,定时器、多线程等等
对于一个复杂问题,解决方法之一就是抽象,苹果为解决上面的问题,抽象出了RunLoop对象,RunLoop中包含多个Mode类,每个mode类中包含若干个 Source,Observer和Timer类,关系如下:

Mode是RunLoop的运行模式,有五类:
kCFRunLoopDefaultMode //App的默认Mode,通常主线程是在这个M

本文深入浅出地介绍了Objective-C中的RunLoop机制,包括RunLoop的基本概念、与线程的关系、不同模式的作用及应用场景,同时还提供了解决卡顿问题的具体实现方案。
最低0.47元/天 解锁文章
3424

被折叠的 条评论
为什么被折叠?



