iOS-消息循环RunLoop详解

RunLoop,跑圈。在iOS开发中,也就是运行循环。

在应用需要的时候自己跑起来运行,在用户没有操作的时候就停下来休息。充分节省CPU资源,提高程序性能。

. RunLoop的概念与作用

概念:一般来讲,一个线程一次只能执行一个任务,执行完成后线程就会退出。但是有时候我们需要线程能够一直“待命”随时处理事件而不退出,这就需要一个机制来完成这样的任务。

例如一个应用放那里,不进行操作就像静止休息一样,点击按钮,就有响应,就像“随时待命”一样,这就是RunLoop的功劳。

所以RunLoop 实际上就是一个对象,这个对象管理了其需要处理的事件和消息,并提供了一个入口函数来执行RunLoop 的逻辑。 

线程开始这个函数之后,便一直会处于此函数 "接受消息->等待->处理" 的循环中:(有事:做出反应;   木事:休眠省电;   再次有事:重新唤醒、处理事件。)

直到这个循环结束(比如传入 quit 的消息),最后函数返回。

作用:

  1. 保持程序持续运行:例如程序一启动就会开一个主线程,主线程一开起来就会跑一个主线程对应的RunLoop,RunLoop保证主线程不会被销毁,也就保证了程序的持续运行;
  2. 处理App中的各种事件(比如:触摸事件,定时器事件,Selector事件等 );
  3. 节省CPU资源,优化程序性能:程序运行起来时,当什么操作都没有做的时候,RunLoop就通知系统,现在没有事情做,然后进行休息待命状态,这时系统就会将其资源释放出来去做其他的事情。当有事情做,也就是一有响应的时候RunLoop就会立马起来去做事情;

RunLoop,最重要的作用,也就是用来管理线程的。可以说,没有线程,也就没有RunLoop的存在必要。

当线程的RunLoop一开启,RunLoop便开始对线程进行管理工作:在线程执行完任务后,线程便会进入休眠状态,并且不会退出,随时等待新的任务。

三、RunLoop与线程的关系

1.每条线程都有唯一的一个与之对应的RunLoop对象;

2.RunLoop在第一次获取时创建,在线程结束时销毁;只能在一个线程的内部获取其 RunLoop(主线程除外)。

3.主线程的RunLoop系统默认启动,子线程的RunLoop需要主动开启;

其实在我们每次建立项目的时候,就已经使用上了RunLoop。

 
 
(这里只是粗略的知识点,主要的看下面截图)
 
只有主线程的消息循环默认开启,子线程的消息循环默认不开启
 
(个人理解) 每一个输入源或定时源都必须对应一个模式(只有与消息循环的模式对应上了,,这里的定时源才会执行)
 
    消息循环是在一个指定的模式下运行的 默认的模式NSDefaultRunLoopMode,设置的输入事件也需要指定一个模式,消息循环的模式必须和输入事件的模式匹配才会执行
 
UITrackingRunLoopMode  当滚动scrollView的时候,消息循环的模式会改变成这种
 
 
使用消息循环的时候必须指定两件事情
    
    1 .   输入事件:输入源和定时源
      2 .  消息循环的模式
 
eg:
 
//  这里的self,是selector里面的方法的所属对象
//  userInfo 是方法跟的参数
NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(demo) userInfo:nil repeats:YES];
   
//把定时器添加到当前线程消息循环中                        这个就是定时源的模式
[[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];

currentRunLoop  当前的消息循环吧
 
***********
- (void)demo {
    //输出当前消息循环的模式
    NSLog(@"%@",[NSRunLoop currentRunLoop].currentMode);
}
 
 

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
   
    //  这里的self,是selector里面的方法的所属对象
    //  userInfo 是方法跟的参数
    NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(demo) userInfo:nil repeats:YES];
   
    //把定时器添加到当前线程消息循环中                        这个就是定时源的模式
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];

    // (个人理解) 每一个输入源或定时源都必须对应一个模式(只有与消息循环的模式对应上了,,这里的定时源才会执行)
    //消息循环是在一个指定的模式下运行的 默认的模式NSDefaultRunLoopMode,设置的输入事件也需要指定一个模式,消息循环的模式必须和输入事件的模式匹配才会执行

    //UITrackingRunLoopMode  当滚动scrollView的时候,消息循环的模式会改变成这种
}

- (void)demo {
    //输出当前消息循环的模式
    NSLog(@"hello %@",[NSRunLoop currentRunLoop].currentMode);
}

@end
原文地址:https://www.cnblogs.com/ibelieveyou/p/6773054.html