“[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]”是做什么用的?

5

我遇到了一些关于NSRunLoop的问题。当运行以下代码时,主线程似乎停止了,而且在while循环后面的代码不会执行。 我想知道当执行[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]时,主线程的runloop会发生什么?我们知道UI主线程的runloop会在应用程序启动时自动运行,那么主线程是睡眠还是处于死循环中?

while (!self.runLoopThreadDidFinishFlag) {
    NSLog(@"Begin RunLoop");

    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];

    NSLog(@"End RunLoop");
}
1个回答

4
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]

这段代码只让线程执行循环中的任务一次,如果没有任务则立即返回。因此这些代码不会阻塞您的主线程。主线程的runloop自动运行,意味着主线程保持一个while循环来执行[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]],一遍又一遍。当它进入你自己的while循环while (!self.runLoopThreadDidFinishFlag)时,状态可能总是为true,这可能会阻塞线程。在这里,你自己的代码[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]的含义是执行循环中的任务一次或清除循环中的任务,如果有一个任务改变了self.runLoopThreadDidFinishFlag,那么你的代码将继续执行。
因此,在你的while循环中的[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]使得主线程有机会执行其他代码,这些代码可能会修改runLoopThreadDidFinishFlag
PS. [NSRunLoop run]runMode:beforeDate:非常不同,你可能会感到困惑。NSRunLoop苹果文档

编辑20190606。主运行循环(主线程)中while循环的示例代码。

你可以测试一下,如果删除"runMode:beforeDate:"函数,那么while循环就无法被"Stop"按钮停止。因此,在这里"runMode:beforeDate:"给了一个机会来运行大while循环(主运行循环)中的其他代码。

- (IBAction)stopMyLoop:(id)sender {
    self.runLoopThreadDidFinishFlag = YES;
    NSLog(@"stopMyLoop");
}

- (IBAction)startMyLoop:(id)sender {
    NSLog(@"startMyLoop");
    self.runLoopThreadDidFinishFlag = NO;
    while (!self.runLoopThreadDidFinishFlag) {
        NSLog(@"Begin RunLoop");
        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate date]];
        NSLog(@"End RunLoop");
    }
}

1
“你说的‘while circle’是什么意思?它让主线程有机会执行其他可能会改变runLoopThreadDidFinishFlag的代码吗?我认为只有当主运行循环有输入源需要处理时,主线程才会被阻塞并最终更改标志。” - slow
@slow 是的。我还在原回答中添加了一些示例代码。我将“beforeDate”更改为当前日期,这样我们的 while 循环就可以正常工作,并且可以随时启动和停止。 - rotoava

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接