Runloop

作者: 轻轻语焉 | 来源:发表于2018-02-08 11:48 被阅读14次

1、Runloop 和 线程 的关系

1、runloop与线程是一一对应的,一个runloop对应一个核心的线程,为什么说是核心的,是因为runloop是可以嵌套的,但是核心的只能有一个,他们的关系保存在一个全局的字典里。

2、runloop是来管理线程的,当线程的runloop被开启后,线程会在执行完任务后进入休眠状态,有了任务就会被唤醒去执行任务。

3、runloop在第一次获取时被创建,在线程结束时被销毁。

4、对于主线程来说,runloop在程序一启动就默认创建好了。

5、对于子线程来说,runloop是懒加载的,只有当我们使用的时候才会创建,所以在子线程用定时器要注意:确保子线程的runloop被创建,不然定时器不会回调。

2、Runloop 介绍

CFRunLoopRef:代表RunLoop的对象 

CFRunLoopModeRef:RunLoop的运行模式 

CFRunLoopSourceRef:就是RunLoop模型图中提到的输入源/事件源 

CFRunLoopTimerRef:就是RunLoop模型图中提到的定时源 

CFRunLoopObserverRef:观察者,能够监听RunLoop的状态改变

2.1 运行模式

每次RunLoop启动时,只能指定其中一个运行模式(CFRunLoopModeRef),这个运行模式(CFRunLoopModeRef)被称作CurrentMode。

如果需要切换运行模式(CFRunLoopModeRef),只能退出Loop,再重新指定一个运行模式(CFRunLoopModeRef)进入。

这样做主要是为了分隔开不同组的输入源(CFRunLoopSourceRef)、定时源(CFRunLoopTimerRef)、观察者(CFRunLoopObserverRef),让其互不影响。

NSDefaultRunLoopMode:App的默认Mode,通常主线程是在这个Mode下运行

UITrackingRunLoopMode:界面跟踪Mode,用于ScrollView 追踪触摸滑动,保证界面滑动时不受其他 Mode 影响

UIInitializationRunLoopMode:在刚启动App时第进入的第一个 Mode,启动完成后就不再使用

GSEventReceiveRunLoopMode: 接受系统事件的内部 Mode,通常用不到

NSRunLoopCommonModes:这是一个占位用的Mode,不是一种真正的Mode

2.1.1 NSTimer使用

1、加入到NSDefaultRunLoopMode 模式下

// 定义一个定时器,约定两秒之后调用self的run方法

NSTimer *timer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES];

// 将定时器添加到当前RunLoop的NSDefaultRunLoopMode下

[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];

等同于下面的写法

// 等效于上面的写法 这句代码调用了scheduledTimer返回的定时器,NSTimer会自动被加入到了RunLoop的NSDefaultRunLoopMode模式下。 [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES];

当页面中存在scrollView 滑动的时候,runloop的模式会切换到 UITrackingRunLoopMode,此时定时器任务停止。

2、加入 UITrackingRunLoopMode 模式下(测试用,实际中不这么玩)

NSTimer *timer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES];

[[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];

当页面中scrollView 滑动的时候,定时任务才启动运行

3、加入到NSRunLoopCommonModes 模式下

NSTimer *timer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES];[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

将NSTimer添加到当前RunLoop的NSRunLoopCommonModes下,我们就可以让NSTimer在不做操作和拖动scrollView 两种情况下 正常运行。

3、 RunLoop 运行原理

1、通知观察者RunLoop已经启动

2、通知观察者即将要开始的定时器

3、通知观察者任何即将启动的非基于端口的源

4、启动任何准备好的非基于端口的源

5、如果基于端口的源准备好并处于等待状态,立即启动;并进入步骤9

6、通知观察者线程进入休眠状态

7、将线程置于休眠知道任一下面的事件发生:  1、  某一事件到达基于端口的源 定时器启动     2、 RunLoop设置的时间已经超时    3、 RunLoop被显示唤醒

8、通知观察者线程将被唤醒

9、处理未处理的事件  :1、如果用户定义的定时器启动,处理定时器事件并重启RunLoop。进入步骤2       2、如果输入源启动,传递相应的消息      3、如果RunLoop被显示唤醒而且时间还没超时,重启RunLoop。进入步骤2

10、通知观察者RunLoop结束。





    

相关文章

网友评论

      本文标题:Runloop

      本文链接:https://www.haomeiwen.com/subject/svnzzxtx.html