RunLoop concept

  • RunLoopIt’s maintained internallyEvent LoopCome to the rightEvent/MessageAn object to manage
  • Sleep to avoid resource usage when there is no message processing; Wake up immediately when a message needs to be processed
  1. whymainFunction does not exit
int main(int argc, char * argv[]) {
    @autoreleasepool {
        returnUIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); }}Copy the code

UIApplicationMain internally turns on the main thread RunLoop by default and executes an infinite loop (not a simple for loop or while loop). UIApplicationMain never returns, receiving processing messages and waiting for sleep, so after running the program, It keeps running continuously

RunLoop structure

  • Source1Based on:PortCommunication between threads
  • Source0: Touch event,PerformSelector
  • TimerTimer:
  • Observer: listener, used to listenRunLoopThe state of the

RunLoop and thread

  • Threads andRunLoopIs one – to – one, the mapping is stored in a globalDictionaryIn, threads act askey.RunLoopAs avalue
  • Self-created threads are disabled by defaultRunLoopthe
  • runloopIs created on the first fetch and destroyed at the end of the thread
  • For the main thread,runloopIt is created by default as soon as the program starts
  • For child threads,runloopIt is lazy to load and is only created when we use it, so take care when using a timer on a child thread: make sure that the child thread isrunloopWas created, or the timer will not be called back
  1. How do I create a resident thread
  • Start one for the current threadRunLoop(First call[NSRunLoop currentRunLoop]Method is actually created firstRunLoop)
  • To the currentRunLoopAdd aPort/SourceSuch as maintainingRunLoopEvent loop (ifRunLoopthemodeIn aitemAll have no,RunLoopWill quit)
  • Start theRunLoop
@autoreleasepool {
  NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
  [runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
  [runLoop run];
}
Copy the code
  1. Print the sequence of the following code
NSLog(@"1");

dispatch_async(dispatch_get_global_queue(0, 0), ^{
  NSLog(@"2");
  [self performSelector:@selector(test) withObject:nil afterDelay:10];
  NSLog(@"3");
});

NSLog(@"4");

- (void)test{
  NSLog(@"5");
}
Copy the code

If an afterDelay function is created, an NSTimer will be created internally and added to the current thread’s RunLoop. If the current thread does not have RunLoop enabled, the method will fail.

dispatch_async(dispatch_get_global_queue(0, 0), ^{
  NSLog(@"2");
  [[NSRunLoop currentRunLoop] run];
  [self performSelector:@selector(test) withObject:nil afterDelay:10];
  NSLog(@"3");
});
Copy the code

The test method is still not executed because: If the mode of the RunLoop has no item, the RunLoop will exit. That is, after calling RunLoop’s run method, the RunLoop will exit anyway, since no item has been added to its mode to maintain the RunLoop’s event loop, so we start RunLoop ourselves. Be sure to add item after

dispatch_async(dispatch_get_global_queue(0, 0), ^{
  NSLog(@"2");
  [self performSelector:@selector(test) withObject:nil afterDelay:10];
  [[NSRunLoop currentRunLoop] run];
  NSLog(@"3");
});
Copy the code

Attached: my blog address