RunLoop常见的面试题

RunLoop常见的面试题,第1张

1.讲讲RunLoop,项目中有用到吗?

RunLoop顾名思义就是程序在运行过程中循环做一些事情.如果没有RunLoop的话,程序运行结束以后就会马上退出的.而我们OC的main函数系统自动为我们创建了RunLoop函数,所以程序并不会马上退出,而是保持运行状态,监听用户的相关 *** 作.

RunLoop的基本作用:

保持程序的持续运行;处理App中的各种事件(比如触摸事件,定时器事件等)节约CPU资源,提高程序性能.该做事的时候做事,该休息的时候休息.

RunLoop 的应用范畴:

定时器,GCD Async Main Queue,事件响应,手势识别,界面刷新,网络请求,AutoreleasePool,performSelector:on Thread

RunLoop 对象:

ios中有2套API来访问和使用RunLoop:

方式一:Foundation框架中的:NSRunLoop方式二:Core Foundation框架中的:CFRunLoopRef(开源的)

  NSRunLoop和CFRunLoopRef都代表着RunLoop对象,而 NSRunLoop是对CFRunLoopRef的一层OC封装.

RunLoop 相关的五个类: 

CFRunLoopRef--->

NSRunLoop对象是OC对象,是对CFRunLoopRef的封装,可以通过getCFRunLoop方法获取其对应的CFRunLoopRef对象。注意,NSRunLoop不是线程安全的,但CFRunLoopRef是线程安全的

CFRunLoopModeRef-->

NSRunLoop对象是一系列RunLoopMode的集合,每个mode包括有这个模式下所有的Source源、Timer源和观察者。每次RunLoop调用的时候都只能调用其中的一个mode,接收这个mode下的源,通知这个mode下的观察者。这样设计的主要目的就是为了隔离各个模式下的源和观察者,使其不相互影响,常用的五种模式:

 kCFRunLoopDefaultMode:

​​​​​​​ App默认的mode,一般情况下App都是运行在这个mode  下的

 UITrackingRunLoopMode:

界面跟踪时的mode,一般用于ScrollView滚动的时候追 踪的,保证滑动的时候不受其他事件影响

UIInitializationRunLoopMode:

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

GSEventReceiveRunLoopMode:

接受系统事件的内部 Mode,一般用不到

kCFRunLoopCommonModes:

占位mode,可以向其中添加其他mode用以检测多个mode的事件

3.​​​​​​​​​​CFRunLoopSourceRef--->事件源产生的地方

​​​​​​​4.CFRunLoopTimerRef-->是基于事件的触发器,其中包含一段时间长度、延期容忍度和一个函数指针(回调方法)。当其加入到RunLoop中时,RunLoop会注册一个时间点,当到达这个时间点后,会触发对应的事件。​​​​​​​

5.CFRunLoopObserverRef-->RunLoop的观察者。每个观察者都可以观察RunLoop在某个模式下事件的触发并处理

kCFRunLoopEntry:即将进入runLoop

kCFRunLoopBeforeTimers:即将处理Timer

kCFRunLoopBeforeSources:即将处理Source

kCFRunLoopBeforeWaiting:即将进入休眠

kCFRunLoopAfterWaiting:刚从休眠中被唤醒

kCFRunLoopExit:即将退出RunLoop

CFRunLoopModeRef代表RunLoop的运行模式

一个RunLoop包含若干个Mode,每个Mode又包含若干个Source0/ Source1/Timer/ObserverRunLoop启动时只能选择其中一个Mode,作为currentMode如果需要切换Mode,只能退出当前Loop,在重新选择一个Mode进入(不同组的Source0/ Source1/Timer/Observer能分隔开,互不影响)如果Mode中没有任何Source0/ Source1/Timer/Observer,RunLoop会立马退出.

RunLoop的运行逻辑:

    mode下面的item

 Source0:触摸事件/perform SelectorsSource1:基于Port的线程间隙Timer:定时器/NSTimerObserver:监听器/用于监听RunLoop的状态.

   运行逻辑:

 通知Observers ,进入Loop;通知Observers,即将处理Timers;通知Observers即将处理 Sources;处理Blocks;处理 Source0(可能会再次处理Blocks);如果存在Source1,就会跳转到第8步;通知Observers开始休眠(等待消息唤醒);通知Observers结束休眠(被某个消息唤醒)​​​​​​​--->1.如果是Timer唤醒了就处理Timer;2.如果是GCD唤醒了就处理CGD;3.如果是Source1唤醒了就处理Source1.处理Blocks;根据当前的执行结果,决定如何 *** 作--->1.回到第2步;2.退出Loop.通知Observers退出Loop. 2.RunLoop内部实现逻辑? 3.RunLoop和线程的关系? 每条线程都有唯一的一个与之对应的RunLoop对象;RunLoop保存在一个全局的Dictionary里,线程作为key,RunLoop作为Value(源码可以证明);线程刚创建时并没有RunLoop对象,RunLoop会在第一次获取它时创建;RunLoop会在线程结束时候销毁. 4.timer和RunLoop的关系?
/**
     第一种方法:
     1.此方法的创建定时器默认会加到了NSRunLoop中,并设置运行模式为默认.
     2.如是想在子线程中开启NSRunLoop,需要手动开启:
     NSRunLoop*runllop=[NSRunLoop currentRunLoop];等到线程销毁的时候currentRunLoop的对象也随之销毁;
     3.在子线程的定时器,需要手动加入runLoop,不要忘记调用run方法
     */
    
    [NSTimer scheduledTimerWithTimeInterval:3.0 target:self selector:@selector(startTime) userInfo:nil repeats:YES];


    /**
     第二种方法:
     1.此方法创建需要手动将定时器添加到 NSRunLoop中,指定的运行模式是default,但是有滚动事件的时候,定时器就会停止工作.
     解决方案:更改NSRunLoop的运行模式.UITrackingRunLoopMode界面追踪,此模式只有发生滚动事件的时候才会开启定时器.若是任何时候都会开启定时器:NSRunLoopCommonModes(NSRunLoopCommonModes=NSDefaultRunLoopMode+UITrackingRunLoopMode).凡是添加到NSRunLoopCommonModes中的事件都会被同时添加到CommonMode的运行模式上的.
     */
    NSTimer*timer=[NSTimer timerWithTimeInterval:3.0 target:self selector:@selector(startTime) userInfo:nil repeats:YES];
    //下面这三种情况根据实际情况加入RunLoop
    [[NSRunLoop currentRunLoop]addTimer:timer forMode:NSDefaultRunLoopMode];
    [[NSRunLoop currentRunLoop]addTimer:timer forMode:NSRunLoopCommonModes];

    [[NSRunLoop currentRunLoop]addTimer:timer forMode:UITrackingRunLoopMode];
5.程序中添加每3秒响应一次的NSTimer,当拖动tableview时候timer可能无法响应要怎么解决? 6.RunLoop是怎么响应用户 *** 作的,具体流程是什么样的? 7.说说RunLoop的几种状态? 8.RunLoop的model作用是什么?

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/993509.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存