NSRunLoop入门(一):简单介绍及(简单)使用 您所在的位置:网站首页 nsrunloop本质 NSRunLoop入门(一):简单介绍及(简单)使用

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

2023-08-23 20:01| 来源: 网络整理| 查看: 265

废话

我负责维护的已经生长了10多年代码中,富含各种pthread与CFRunLoop接口,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; }


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

      专题文章
        CopyRight 2018-2019 实验室设备网 版权所有