了解NSRunLoop

任何人都可以解释什么是NSRunLoop ? 所以我知道NSRunLoop是一个与NSThread连接的东西吗? 所以假设我创build了一个线程

 NSThread* th=[[NSThread alloc] initWithTarget:self selector:@selector(someMethod) object:nil]; [th start]; -(void) someMethod { NSLog(@"operation"); } 

所以这个线程完成后,他的工作权利? 为什么使用RunLoops或在哪里使用? 从苹果文档我已经看了一些东西,但不清楚,所以请尽可能简单解释

运行循环是一个抽象(除其他外)提供了一种处理系统input源(套接字,端口,文件,键盘,鼠标,定时器等)的机制。

每个NSThread都有自己的运行循环,可以通过currentRunLoop方法访问。

通常,您不需要直接访问运行循环,尽pipe有一些(networking)组件可能允许您指定将用于I / O处理的运行循环。

给定线程的运行循环将等待一个或多个input源有一些数据或事件,然后触发相应的input处理程序来处理每个“准备就绪”的input源。

这样做后,它将返回到它的循环,处理来自各种来源的input,并在没有工作要做的时候“睡觉”。

这是一个非常高层次的描述(试图避免太多的细节)。

编辑

试图解决评论。 我把它分解成碎片。

  • 这意味着我只能访问/运行在线程内运行循环吧?

确实。 NSRunLoop不是线程安全的,只能从运行循环的线程的上下文访问。

  • 有没有简单的例子如何添加事件来运行循环?

如果你想监视一个端口,你只需要将该端口添加到运行循环中,然后运行循环就会监视该端口的活动。

 - (void)addPort:(NSPort *)aPort forMode:(NSString *)mode 

你也可以添加一个计时器明确的

 - (void)addTimer:(NSTimer *)aTimer forMode:(NSString *)mode 
  • 什么意思,然后将回到其循环?

运行循环将处理所有准备好的事件(根据其模式)。 您需要查看文档以发现运行模式,因为这有点超出了一般答案的范围。

  • 当我启动线程运行循环不活动?

在大多数应用程序中,主运行循环将自动运行。 但是,您负责启动运行循环并响应您旋转的线程的传入事件。

  • 是否有可能添加一些事件线程之外的线程运行循环?

我不确定你在这里的意思。 您不要将事件添加到运行循环中。 您可以添加input源和定时器源(来自拥有运行循环的线程)。 运行循环然后监视它们的活动。 当然,您可以提供来自其他线程和进程的数据input,但input将由正在运行运行循环的线程上监视这些源的运行循环处理。

  • 这是否意味着有时我可以使用运行循环来阻塞线程一段时间

确实。 事实上,一个运行循环将“停留”在一个事件处理程序中,直到事件处理程序返回。 你可以在任何应用程序中看到这一点。 为睡眠的任何IO操作(例如,按下button)安装处理程序。 您将阻止主运行循环(以及整个UI),直到该方法完成。

这同样适用于任何运行循环。

我build议你在运行循环中阅读以下文档:

https://developer.apple.com/documentation/foundation/nsrunloop

以及在线程中如何使用它们:

https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html#//apple_ref/doc/uid/10000057i-CH16-SW1

Runloops有点像一个盒子里发生的事情。

基本上在Runloop,你去处理一些事件,然后返回。 如果在超时命中之前没有处理任何事件,则返回。 你可以说它与asynchronousNSURLConnections类似,在后台处理数据而不干扰你的当前循环,但同时你需要同步数据。 这可以通过Runloop的帮助来完成,它保存你的asynchronousNSURLConnection,并在调用的时候提供数据。 你可以使用Runloop,如下所示:

 NSDate *loopUntil = [NSDate dateWithTimeIntervalSinceNow:0.1]; while (YourBoolFlag && [[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode beforeDate:loopUntil]) loopUntil = [NSDate dateWithTimeIntervalSinceNow:0.1]; 

在这个Runloop中它将运行,直到你完成了一些其他的工作,并将YourBoolFlag设置为false

同样,你可以在线程中使用它们。

希望这可以帮助你。

运行循环是 交互式应用程序与命令行工具分开的东西。

  • 命令行工具通过参数启动,执行它们的命令,然后退出。
  • 交互式应用程序等待用户input,作出反应,然后继续等待。

从这里

它们允许你等待用户点击并作出相应的响应,等待你得到一个完成的处理程序并应用它的结果,等到你得到一个定时器并执行一个function。 如果你不能听用户点击,你不能等到networking通话发生,你不能在x分钟内被唤醒。

也从这个评论 :

后台线程没有自己的runloops,但是你可以添加一个。 例如AFNetworking 2.x做到了。 它在后台线程上被NSURLConnection或者NSTimer使用过,并且是真正的技术,但是我们自己不再这么做了,因为更新的API消除了这种需要。 但是看起来,URLSession 在这里例如是简单的请求 ,正在主队列上运行[见图的左侧面板]完成处理程序,你可以看到它在后台线程上有一个运行循环

NSRunLoop -a

事件驱动模式

项目LightWeightRunLoop实现NSRunLoop 只有不到四百行的代码

https://github.com/wuyunfeng/LightWeightRunLoop

除了使用IO多路复用实现NSRunLoop之外,一些Runloop-Relative Fundation API(例如在其他线程, 定时器URLConnection等)上执行select器 (或延迟一些时间)