CFRunLoopPerformBlock() 处理的块是什么?

What is the block that CFRunLoopPerformBlock() handles?

目前正在学习iOS中的runloop机制。在阅读 Run, RunLoop, Run!CFRunloop 源代码之后,我仍然对它的实际工作原理感到困惑。我的困惑之一是关于 CFRunLoopPerformBlock() 函数。很多文章都提到这个函数会把block入队,在下一个runloop中执行,但是我的问题是:这里的block是什么意思?

假设我有一个非常简单的 CustomViewController。

- (void)viewDidLoad
{
    [super viewDidLoad];
    UIView *redView = [[UIView alloc] initWithFrame:CGRectMake(0, 50, 100, 100)];
    redView.backgroundColor = [UIColor redColor];
    [self.view addSubview:redView];
}

显然这段代码中没有块语法。 viewDidLoad 会被 CFRunLoopPerformBlock() 调用吗?如果不是,runloop 是如何处理这段代码的?

根据 Apple 文档,

This method enqueues a block object on a given runloop to be executed as the runloop cycles in specified modes.

This method enqueues the block only and does not automatically wake up the specified run loop. Therefore, execution of the block occurs the next time the run loop wakes up to handle another input source. If you want the work performed right away, you must explicitly wake up that thread using the CFRunLoopWakeUp function.

您可以在其中传递一段代码作为

 CFRunLoopPerformBlock(CFRunLoopGetMain(), kCFRunLoopCommonModes, ^{
        // your code goes here
    });

Apparently there's no block syntax in this code. Will viewDidLoad be called by CFRunLoopPerformBlock()? If not, how is this snippet handled by runloop?

viewDidLoadCFRunLoopPerformBlock 几乎没有任何关系。 viewDidLoad 只是在加载视图时在我们的视图控制器中调用的一种方法,但在它出现在 UI 中之前,让我们有机会配置我们的 UI .

那么 运行 循环是什么?它只是一个不断 运行ning 的循环,检查各种事件(事件、计时器等)。它在每个 iOS 应用程序的幕后 运行ning,尽管现在我们很少直接与它交互。 (例外情况可能是当我们启动某些类型的计时器时,我们将它们添加到主 运行 循环中。但现在就是这样了。)但是当我们从 viewDidLoad 这样的方法中 return 时,我们将控制权交还给 运行 循环。

what does the block mean here?

一个“块”(在Swift中也称为“闭包”)只是一段代码运行,当这个代码块存储在一个变量中或用作方法的参数。 CFRunLoopPerformBlock 函数实际上是说,“这是在 运行 循环的下一次迭代期间 运行 的一些代码”。该函数的第三个参数是要成为 运行 的代码,并且是代码的“块”(在 Objective-C 中,它以 ^{ 开始并以最终的 } 结束).有关 Objective-C 块的信息,请参阅 Apple 的 Blocks Programming Topics or Programming with Objective-C: Working with Blocks.

说了这么多,值得注意的是人们通常不会使用 CFRunLoopPerformBlock。如果我们想将一段代码调度为 运行,我们现在通常会使用 Grand Central Dispatch (GCD)。例如,这里有一些代码有两个参数,一个队列和一个块:

dispatch_async(dispatch_get_main_queue(), ^{
    self.label.text = @"Done";
});

同样,从 ^{} 的所有内容都是第二个参数的一部分,即块。此代码表示“将更新 labeltext 的代码块添加到主队列。”