面试经典-面试Runloop

Runloop:

    Runloop是事件接收和分发机制的一个实现;

    是线程相关基础框架的一部分;

    

Runloop的目的:

    一个Runloop实质就是一个事件处理的循环:用来不停的调度工作和处理输入事件;

    Runloop循环会在有工作的时候工作,没有工作休眠;实际上,他保证了线程结束前不会被终止;

    如果没有它,主线程执行完启动任务后,就直接结束了;

 

Runloop的使用场景:

    当需要和线程进行交互的时候才会使用;

 

Runloop Mode:

    前文中我们已经知道,Runloop Mode对应的是一个C语言的结构体:其中主要的是source0、source1、observers、timers;

    而Model的不同类型,对应的就是隔绝开来的source、observer、timer的不同组合;

    一个Runloop可以有多个Mode,但在某一时刻Runloop只能运行在一个Mode下,处理此Mode中的source、observer和timer;

 

Model的种类:

    前文中我们已经了解过了关于mode的分类;这里,我们只需要知道,不同的mode集合了各自的source、observer和timer;

    iOS目前公开的只有NSDefaultRunLoopMode(默认的,正常情况下使用)和NSRunLoopCommonModes,NSRunLoopCommonModes是NSDefaultRunLoopMode和NSEventTrackingRunLoopMode(使用这个Mode来跟踪用户交互事件,比如滑动视图的上下滑动)两者的集合;

 

Source:

    即可以唤醒Runloop的一些事件;比如用户点击屏幕,就会创建一个input source;

    ·source0:非系统事件;

        只包含一个回调(函数指针),不能主动触发事件;

        使用时,需要先调用CFRunLoopSourceSignal(source);将这个Source标记为待处理;

        然后手动调用CFRunLoopWakeUp(runloop)来唤醒Runloop,让其处理这个事件;

 

    ·source1:系统事件:

        包含一个mach_port和一个回调(函数指针),被用于通过内核和其他线程相互发送消息;

        这种source能主动唤醒Runloop的线程;

 

Timer:

    使用NSTimer API注册执行的任务,就属于这一类;

 

Observer:

    某个Observer可以监听runloop的状态变化,并作出反应;

 

Runloop的运行流程:

    上一节文中已经画出了RunLoop的完整流程;我们在对该图进行注释下;

 

注解:

    一般从mach_port读取msg,只有主线程的Runloop能做,接受到msg立即处理任务;

    图中有一句话需要修正:每次loop如果处理完了source0任务,就是说不再有source0任务的处理需要线程等待了,此时poll值为true,timeout值为0(可参考上一篇文章);

    

下面我们来看下,那些关于Runloop的常见问题:

1.Runloop和线程是什么关系?

    每个线程都有唯一的与之对应的Runloop对象,主线程的Runloop自动创建(UIApplicationMain()函数),子线程的Runloop需要主动创建;

    Runloop在第一次获取时创建,在线程结束时销毁;

 

2.Runloop的mode作用?

    指定事件在运行循环中的优先级;

    线程的运行根据不同的模式,响应不同的事件组合,处理不同的情形;

 

3.AutoreleasePool和Runloop有什么联系?

    NSRunLoop每次循环过程中NSAutoreleasePool对象被生成或废弃;

    iOS应用启动后会注册两个 Observer 管理和维护 AutoreleasePool;

    应用程序刚刚启动时默认注册了很多个Observer,其中有两个Observer的 callout 都是_wrapRunLoopWithAutoreleasePoolHandler,这两个是和自动释放池相关的两个监听;

    ·第一个 Observer 会监听 RunLoop 的进入,它会回调objc_autoreleasePoolPush() 向当前的 AutoreleasePoolPage 增加一个哨兵对象标志创建自动释放池。这个 Observer 的 order 是 -2147483647 优先级最高,确保发生在所有回调操作之前;

    ·第二个 Observer 会监听 RunLoop 的进入休眠和即将退出 RunLoop 两种状态,在即将进入休眠时会调用 objc_autoreleasePoolPop() 和 objc_autoreleasePoolPush() 根据情况从最新加入的对象一直往前清理直到遇到哨兵对象。而在即将退出 RunLoop 时会调用objc_autoreleasePoolPop() 释放自动自动释放池内对象;这个Observer 的 order 是 2147483647 ,优先级最低,确保发生在所有回调操作之后;

 

4.CFRunLoop和CFRunLoopRef区别?

    CFRunLoopRef 基于C 线程安全,NSRunLoop 基于 CFRunLoopRef 面向对象的API 是不安全的;

 

参考文章:

iOS RunLoop总结以及相关面试题解答

关于runloop,好多人都理解错了!

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值