“[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distanceFuture]]”有什么作用?

Sle*_*mon 5 multithreading objective-c nsthread nsrunloop

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

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

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

    NSLog(@"End RunLoop");
}
Run Code Online (Sandbox Code Playgroud)

rot*_*ava 4

[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]
Run Code Online (Sandbox Code Playgroud)

这行代码只是让线程执行一次循环的源,如果没有任务,则立即返回。所以这些代码不会阻塞你的主线程。主线程的runloop自动运行意味着主线程会保留一段时间循环来[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]反复执行。当它遇到你自己的 while 循环时,while (!self.runLoopThreadDidFinishFlag)状态可能始终为 true,这可能会阻塞线程。这里您自己的代码[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]意味着执行循环的源一次或清理运行循环源中的任务,如果有一个任务更改,self.runLoopThreadDidFinishFlag那么您的代码将继续前进。

所以[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]] 在你的while圈子里让主线程有机会执行goto其他可能改变runLoopThreadDidFinishFlag.

附言。 [NSRunLoop run]runMode:beforeDate:您可能会感到困惑的情况有很大不同。NSRunLoop 苹果文档


编辑20190606。main-runloop(主线程)中while循环的示例代码。

您可以测试一下,如果删除了“runMode:beforeDate:”函数,则while循环无法通过“停止”按钮停止。所以这里的“runMode:beforeDate:”提供了在out big-while-loop(main-runloop)中运行其他代码的机会。

- (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");
    }
}
Run Code Online (Sandbox Code Playgroud)