RunLoop
是经过内部维护的事件循环(Event Loop)
来对事件/消息
进行管理的一个对象main
函数不会退出int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
复制代码
UIApplicationMain
内部默认开启了主线程的RunLoop
,并执行了一段无限循环的代码(不是简单的for循环
或while循环
)UIApplicationMain
函数一直没有返回,不断地接收处理消息以及等待休眠,因此运行程序以后,会保持持续运行状态git
Source1
: 基于Port
的线程间通讯Source0
: 触摸事件、PerformSelector
Timer
: 定时器Observer
: 监听器,用于监听RunLoop
的状态RunLoop
是一一对应的,其映射关系是保存在一个全局的Dictionary
里,线程做为key
,RunLoop
做为value
RunLoop
的runloop
在第一次获取时被建立,在线程结束时被销毁runloop
在程序一启动就默认建立好了runloop
是懒加载的,只有当咱们使用的时候才会建立,因此在子线程用定时器要注意:确保子线程的runloop
被建立,否则定时器不会回调RunLoop
(第一次调用[NSRunLoop currentRunLoop]
方法时,实际是会先去建立一个RunLoop
)RunLoop
中添加一个Port/Source
等维持RunLoop
的事件循环(若是RunLoop
的mode
中一个item
都没有,RunLoop
会退出)RunLoop
@autoreleasepool {
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
[runLoop run];
}
复制代码
NSLog(@"1");
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"2");
[self performSelector:@selector(test) withObject:nil afterDelay:10];
NSLog(@"3");
});
NSLog(@"4");
- (void)test{
NSLog(@"5");
}
复制代码
答案是1423
,test
方法并不会执行 缘由是:若是是带afterDelay
的延时函数,会在内部建立一个NSTimer
,而后添加到当前线程的RunLoop
中,也就是若是当前线程没有开启RunLoop
,该方法会失效 那么咱们改为:github
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"2");
[[NSRunLoop currentRunLoop] run];
[self performSelector:@selector(test) withObject:nil afterDelay:10];
NSLog(@"3");
});
复制代码
test
方法依然不执行 缘由是:若是RunLoop
的mode
中一个item
都没有,RunLoop
会退出 即在调用RunLoop
的run
方法后,因为其mode
中没有添加任何item
去维持RunLoop
的事件循环,RunLoop
随即仍是会退出,因此咱们本身启动RunLoop
,必定要在添加item
后bash
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"2");
[self performSelector:@selector(test) withObject:nil afterDelay:10];
[[NSRunLoop currentRunLoop] run];
NSLog(@"3");
});
复制代码
附:个人博客地址async