0

I'm currently learning the runloop mechanism in iOS. After reading Run, RunLoop, Run! and the CFRunloop source code, I'm still confused about how it really works. One of my confusions is about the CFRunLoopPerformBlock() function. Many articles mentioned that this function will enqueue the block and execute it in the next runloop, but my question is: what does the block mean here?

Let's say I have a very simple CustomViewController.

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

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

Nirav Kotecha
  • 2,493
  • 1
  • 12
  • 26
P. Tsin
  • 435
  • 4
  • 14

2 Answers2

1

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

The viewDidLoad has practically nothing to do with CFRunLoopPerformBlock. The viewDidLoad is just a method that is called in our view controller when the view has been loaded, but before it’s been presented in the UI, to give us a chance to configure our UI.

So what is the run loop? It is just a loop that is constantly running, checking for various events (events, timers, etc.). It’s running behind the scenes in every iOS app, though we rarely interact directly with it nowadays. (The exception might be when we start certain types of timers, we add them to the main run loop. But that’s about it nowadays.) But when we return from methods like viewDidLoad, we’re yielding control back to the run loop.

what does the block mean here?

A “block” (also known as a “closure” in Swift) is just a piece of code to be run, when this code block is stored in a variable or used as a parameter of a method. The CFRunLoopPerformBlock function effectively says, “here is a some code to run during the next iteration of the run loop”. The third parameter of that function is the code to be run, and is the “block” of code (in Objective-C it starts with ^{ and ends with the final }). For information about Objective-C blocks, see Apple's Blocks Programming Topics or Programming with Objective-C: Working with Blocks.

All of this having been said, it’s worth noting that one wouldn’t generally use CFRunLoopPerformBlock. If we want to dispatch a piece of code to be run, we’d generally now use Grand Central Dispatch (GCD). For example, here is some code that has two parameters, a queue and a block:

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

Again, everything from the ^{ to the } is part of that second parameter, which is the block. This code says “add this block of code that updates the text of the label to the main queue.”

Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • Thanks a lot. Very detailed explanation. One more question: why and when we want some code to run in the next runloop iteration? – P. Tsin Aug 21 '19 at 08:06
  • For example, you’re doing something on background thread and you now need to update the UI, something that must happen on the main thread. But the main thread might be busy right now, so you queue it to run when the main thread next becomes available. (But we just don’t use runloops anymore to achieve this. Use GCD.) – Rob Aug 21 '19 at 12:02
0

According to Apple documentation,

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.

You can pass a block of code in it as

 CFRunLoopPerformBlock(CFRunLoopGetMain(), kCFRunLoopCommonModes, ^{
        // your code goes here
    });
Community
  • 1
  • 1
Manav
  • 2,284
  • 1
  • 14
  • 27