开发者联盟

iOS RunLoop

2020-01-17  本文已影响0人  72行代码

RunLoop概念

  1. 为什么main函数不会退出
int main(int argc, char * argv[]) {
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

UIApplicationMain内部默认开启了主线程的RunLoop,并执行了一段无限循环的代码(不是简单的for循环while循环UIApplicationMain函数一直没有返回,不断地接收处理消息以及等待休眠,所以运行程序之后,会保持持续运行状态

RunLoop结构体

RunLoop和线程

  1. 怎么创建一个常驻线程
@autoreleasepool {
  NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
  [runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
  [runLoop run];
}
  1. 输出下边代码的执行顺序
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");
}

答案是1423test方法并不会执行
原因是:如果是带afterDelay的延时函数,会在内部创建一个NSTimer,然后添加到当前线程的RunLoop中,也就是如果当前线程没有开启RunLoop,该方法会失效
那么我们改成:

dispatch_async(dispatch_get_global_queue(0, 0), ^{
  NSLog(@"2");
  [[NSRunLoop currentRunLoop] run];
  [self performSelector:@selector(test) withObject:nil afterDelay:10];
  NSLog(@"3");
});

test方法依然不执行
原因是:如果RunLoopmode中一个item都没有,RunLoop会退出
即在调用RunLooprun方法后,由于其mode中没有添加任何item去维持RunLoop的事件循环,RunLoop随即还是会退出,所以我们自己启动RunLoop,一定要在添加item

dispatch_async(dispatch_get_global_queue(0, 0), ^{
  NSLog(@"2");
  [self performSelector:@selector(test) withObject:nil afterDelay:10];
  [[NSRunLoop currentRunLoop] run];
  NSLog(@"3");
});

附:我的博客地址

上一篇 下一篇

猜你喜欢

热点阅读