iOS复习笔记之 runLoop详解

Posted by fooval on September 21, 2016

什么是runLoop

runLoop 是一个事件处理的循环,用来不停的调动工作以及处理输入事件。在我们进行多线程编程的时候,我们往往希望线程在有任务的时候运行,没有任务的时候能自动休眠,释放cpu的资源,当有事件需要处理的时候线程能够重新唤醒。而runLoop恰巧是做这样的事情。 可以把runLoop理解为一个事件驱动器,没有事件的时候,线程是处于挂起状态。当有事件的时候,runLoop就去唤醒线程,让线程工作。

+ (void)synchronizationThreadEntryPoint:(id)__unused object {
    @autoreleasepool {
        [[NSThread currentThread] setName:@"SynchronizationManager"];
        
        NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
        [runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
        [runLoop run];
    }
}

+ (NSThread *)synchronizationThread {
    static NSThread *_synchronizationThread = nil;
    static dispatch_once_t oncePredicate;
    dispatch_once(&oncePredicate, ^{
        _synchronizationThread = [[NSThread alloc] initWithTarget:self selector:@selector(synchronizationThreadEntryPoint:) object:nil];
        [synchronizationThread start];
    });
    
    return _synchronizationThread;
}

...

[self performSelector:@selector(messageTransaction:) onThread:[[self class]synchronizationThread ] withObject:notify waitUntilDone:NO modes:[self.runLoopModes allObjects]];

以上代码是我项目的使用的是一个后台的数据同步的常住线程。包括了如何创建创建一个后台线程然后加入一个runLoop。

runLoop 的作用

  • 保持程序的持续运行(比如主运行循环)
  • 处理App中的各种事件(比如触摸事件、定时器事件、Selector事件)
  • 节省CPU资源,提高程序性能:该做事时做事,该休息时休息

runLoop 的工作流程

runLoop runLoopRun

runloop的输入源

  • 基于端口的输入源(Port Sources)。通过内置的端口相关的对象和函数,创建配置基于端口的输入源。是由内核自动发送。
  • 自定义输入源(Custom Sources)。使用CFRunLoopSourceRef对象创建,它需要自定义自己的行为和消息传递机制
  • Cocoa执行Selector的源(”performSelector…方法” Sources)。Selector执行完成后会自动从Run Loop上移除
  • 定时源(Timer Sources ) 。如NSTimer

runLoop的运行模式

一个runLoop只能有一个运行模式:

  • NSDefaultRunLoopMode(kCFRunLoopDefaultMode):runLoop默认的model,空闲状态
  • UITrackingRunLoopMode ScrollView滑动时会切换到这个model(系统使用的)
  • UIInitializationRunLoopMode 启动时的mode,启动结束后这个mode就不在使用了(系统使用的)。
  • NSRunLoopCommonModes(kCFRunLoopCommonModes):Mode集合

参考资料

RunLoop剖析

runLoop详解

深入理解runLoop