NSRunLoop入门(一):简单介绍及(简单)使用

废话

我负责维护的已经生长了10多年代码中,富含各种pthreadCFRunLoop接口,pthread很简单,一看就懂,一点就会。但对于RunLoop的概念,从入门Mac开发到现在,看了很多资料也一直都不得其要领。(一定是我太笨!)

今日突然灵光一现,对此概念小有成就,是以发布此文,帮助新人理解。

NSRunLoop介绍

NSRunLoop本质一个while ture的循环,但不仅仅是一个while ture循环,我们可以究极简化NSLoop为:

while(true){
  sleep(1);
}

看起来,好像入门级小白也能写出来上方的代码,那么苹果为什么费这么大力气搞一个这样的玩意儿呢?
NSRunLoop存在的原因之一,NSRunLoop在休眠时,不会占用系统任何资源!

NSRunLoop简单使用

在我入门时,遇到了一个奇怪的场景,具体的场景我忘了,但类似场景可由以下操作复现。

阶段一:无循环,无输出

创建一个控制台程序,代码如下:

#import 
int main(){
   dispatch_async(dispatch_get_main_queue(), ^{
       NSLog(@"窝窝头,1块钱4个,嘿嘿!");
    });
    return 0;
}

编译,运行,满怀期待地等待控制台输出,然而....什么也没输出,程序就关闭了。
这是因为:异步执行的代码还没开始执行的时候,主线程已经执行完操作退出了,所以异步执行的操作就没法完成了。

阶段二:死循环,无输出

那么问题来了,如果我想让异步执行的代码执行完之后,主线程再退出,应该怎么搞?相信聪明的读者肯定脑海中有想法了,那就是:

#import 
int main(){
    __block bool isFinish = false;
    dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"窝窝头,1块钱4个,嘿嘿!");
        isFinish = true;
    });
    while(!isFinish){
        sleep(1);
    }
    return 0;
}

编译,运行,等待....(3 thousand hours later)
看起来程序死循环了,为啥呢?
因为异步执行的代码我们选择的是主队列,而主队列此时正在“手动“写的RunLoop中阻塞着,无法抽身。

阶段三:死循环,有输出

我们"手动"写的RunLoop,会一直阻塞住,没有办法调度它去执行我们异步操作的代码,那么如果我们使用系统的NSRunLoop呢?代码如下:

#import 
int main(){
    NSRunLoop *rl = [NSRunLoop currentRunLoop];
    dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"窝窝头,1块钱4个,嘿嘿!");
    });
    [rl run];
    return 0;
}

编译,运行,等待...终于出现了熟悉的窝窝头叫卖声,BUT,程序也一直RunLoop下去了。
但,通过上述例子,我相信各位能够体验到RunLoop是一个while ture循环这句话了。

阶段四:无循环,有输出

那么,问题来了,我如果不想让程序RunLoop怎么办呢?我只想让它输出叫卖声,然后程序结束。

我们可以进一步学习使用NSRunLoop,等到异步操作完成之后,退出Runloop即可。
代码如下:

#import 
int main(){
    NSRunLoop *rl = [NSRunLoop currentRunLoop];
    NSPort *p = [NSMachPort port];
    dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"窝窝头,1块钱4个,嘿嘿!");
        [rl removePort:p forMode:NSDefaultRunLoopMode];
    });
    [rl addPort:p forMode:NSDefaultRunLoopMode];
    [rl runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
    return 0;
}

你可能感兴趣的:(NSRunLoop入门(一):简单介绍及(简单)使用)