RunLoop 高频面试题及详细答案(实战版)_第1页
RunLoop 高频面试题及详细答案(实战版)_第2页
RunLoop 高频面试题及详细答案(实战版)_第3页
RunLoop 高频面试题及详细答案(实战版)_第4页
RunLoop 高频面试题及详细答案(实战版)_第5页
已阅读5页,还剩2页未读, 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

RunLoop高频面试题及详细答案(实战版)一、基础概念类(初级面试必问)1.什么是RunLoop?核心作用是什么?答案:RunLoop是iOS/macOS基于CFRunLoop封装的一套事件循环机制,本质是一个死循环。简单来说:线程默认执行完任务就会立即销毁,而RunLoop的作用就是保活线程、让线程持续待命、等待并处理事件,不会执行完代码就退出。核心三大作用:1.保活线程:让线程不自动销毁,常驻内存待命2.监听事件:实时处理触摸、滑动、定时器、网络回调、端口消息等事件3.节省性能:无事件时线程休眠,不占用CPU资源;有事件再唤醒执行2.RunLoop和线程的关系是什么?答案:1.一一对应、线程私有:每一个线程都有且仅有一个专属的RunLoop,二者绑定关系永久不变。2.主线程RunLoop默认自动创建、自动开启,App启动后全程常驻,不会停止。3.子线程RunLoop默认不存在,需要手动获取、手动开启,不主动调用就不会创建和运行。4.线程销毁时,对应的RunLoop也会随之销毁,无法单独存在。底层存储方式:通过线程的ThreadDictionary存储,保证线程私有、不共享。3.iOS中有几种RunLoop?区别是什么?答案:分为两种,本质底层都是CFRunLoop,只是封装层级不同:NSRunLoop:OC高层封装,面向开发者,API简单易用,但功能有限CFRunLoop:C语言底层源码,开源,功能完整、精度更高,可精准控制运行模式、状态核心区别:日常开发用NSRunLoop,底层逻辑、源码实现、性能优化全部依赖CFRunLoop。二、核心原理类(中级核心考点)4.RunLoop的核心组成模块有哪些?答案:RunLoop整体由5大核心模块构成,缺一不可:CFRunLoop(循环主体):整个循环的载体,负责调度所有事件、控制循环启停CFRunLoopMode(运行模式):事件筛选规则,RunLoop同一时间只处于一种模式,只处理当前模式下的事件CFRunLoopSource(事件源):分为Source0、Source1,负责接收用户操作、系统端口事件CFRunLoopTimer(定时器源):NSTimer、CADisplayLink的底层依赖,定时触发任务CFRunLoopObserver(观察者):监听RunLoop的生命周期状态,在循环启动、休眠、唤醒、退出时触发回调5.详细说下RunLoop的几种运行Mode?各自使用场景?答案:常用的5种Mode,核心是前3种:kCFRunLoopDefaultMode/NSDefaultRunLoopMode(默认模式)日常闲置状态、页面加载、普通业务任务执行,默认RunLoop所处模式。滑动屏幕时会自动切换模式,此模式下任务会暂停。UITrackingRunLoopMode(滑动模式)手指滑动UIScrollView、TableView、CollectionView时,RunLoop自动切换到此模式。优先级最高,保证滑动流畅、不卡顿,Default模式下的定时器、任务会暂停。kCFRunLoopCommonModes(通用模式)伪模式,不是独立运行模式,是Default+Tracking的集合。添加到CommonModes的任务,在默认、滑动两种状态下都能执行,不会暂停。其余两种:UIInitializationRunLoopMode(APP初始化专用)、GSEventReceiveRunLoopMode(系统事件接收专用),开发中基本不用。6.Source0和Source1的区别?答案:两者都是RunLoop事件源,核心区别是触发方式和层级不同:Source0(非端口事件、手动触发)纯App内部事件,无系统端口依赖,需要手动标记、手动唤醒RunLoop才会执行。常见场景:UI点击、手势事件、performSelector任务Source1(端口事件、系统自动触发)依赖系统内核端口,由系统底层自动监听、自动唤醒RunLoop,优先级更高、响应更快。常见场景:网络回调、进程间通信、系统消息推送7.RunLoopObserver的监听状态有哪些?答案:Observer可以精准监听RunLoop6个生命周期节点,也是卡顿监控、保活线程的核心原理:kCFRunLoopEntry:即将进入RunLoop循环kCFRunLoopBeforeTimers:即将处理定时器任务kCFRunLoopBeforeSources:即将处理Source事件任务kCFRunLoopBeforeWaiting:即将进入休眠(最常用,卡顿监控核心节点)kCFRunLoopAfterWaiting:从休眠中被唤醒,开始处理事件kCFRunLoopExit:RunLoop循环即将退出三、运行流程与源码逻辑(中高级考点)8.详细描述RunLoop一次完整的循环流程答案:RunLoop单次循环的完整执行顺序,面试口述标准流程:1.进入循环:触发Entry观察者回调2.预处理定时器:触发BeforeTimers回调,优先处理所有到期的Timer任务3.预处理事件源:触发BeforeSources回调,处理Source0、Source1待执行事件4.判断是否休眠:如果当前没有任何待处理任务,触发BeforeWaiting回调,线程进入休眠,等待系统唤醒5.被唤醒执行任务:有定时器、端口、手动唤醒信号时,触发AfterWaiting回调,依次执行对应任务6.判断循环是否继续:若无终止条件,重复上述流程;若满足退出条件,触发Exit回调,结束循环9.RunLoop为什么不会卡死主线程?死循环为什么不耗性能?答案:这是高频反问题,核心关键点:RunLoop不是忙循环,是休眠等待机制。普通while死循环会一直占用CPU轮询判断,持续消耗性能;而RunLoop无任务时会调用内核mach_wait方法,让线程进入内核休眠状态,彻底释放CPU资源,不占用任何算力。只有当定时器到期、有触摸事件、端口消息、手动唤醒信号时,系统才会主动唤醒线程,执行对应任务,执行完成后再次休眠,因此性能极低、不会卡顿。四、定时器实战问题(高频实操考点)10.NSTimer为什么滑动TableView会暂停?怎么解决?答案:暂停原因:NSTimer默认添加在NSDefaultRunLoopMode模式下。当手指滑动列表时,主线程RunLoop会自动切换到UITrackingRunLoopMode,此时Default模式下的所有任务(包括定时器)都会暂停,滑动结束切回默认模式后才会继续执行。解决方案(三种):1.将Timer添加到kCFRunLoopCommonModes,兼容默认和滑动模式,全程不暂停2.使用GCD定时器,GCD定时器不依赖RunLoop,不受Mode影响3.使用CADisplayLink,同样依赖RunLoop,但配置CommonModes可解决暂停问题11.NSTimer为什么会卡顿、不准时?GCD定时器为什么更精准?答案:NSTimer不准的核心原因:1.依赖RunLoop调度,如果RunLoop当前线程卡顿、任务堆积,定时器触发时机就会延后2.受RunLoopMode切换影响,滑动时会暂停、延后执行3.NSTimer是事件触发机制,不是实时计时,任务堆积时会合并触发,丢失精度GCD定时器优势:GCD定时器基于系统内核时钟,不依赖RunLoop调度,不受线程任务、Mode切换影响,系统优先保障计时精度,因此更稳定、更准时。12.NSTimer的循环引用问题怎么解决?原理是什么?答案:循环引用成因:控制器强引用Timer,Timer强引用target(控制器),导致双方互相持有,页面无法释放。常规解决方案及坑点:1.weak修饰target(无效):NSTimer内部会对target做retain操作,weak无法打破持有关系2.手动invalidate:页面销毁前手动销毁定时器,常规基础方案,但容易遗漏、时机不对导致崩溃3.中间代理封装(最优方案):通过弱引用的中间类承接Timer回调,打破直接持有关系,彻底解决循环引用4.GCD定时器替代:无循环引用问题,无需手动处理持有关系五、子线程RunLoop常驻保活(工程实战考点)13.如何实现子线程常驻?核心注意点有哪些?答案:子线程默认执行完任务立即销毁,想要常驻必须开启RunLoop,标准实现流程:1.自定义子线程,全局强引用线程对象,避免提前释放2.获取线程对应的RunLoop,手动添加一个空的Source/Timer占位(必须步骤)3.手动调用run方法开启循环,保活线程核心注意点(面试重点):RunLoop必须添加常驻事件源(Source/Timer),否则开启后会立即自动退出循环,无法保活线程。因为RunLoop启动时会检测当前是否有待监听任务,无任务则直接终止循环。14.子线程RunLoop如何精准退出?直接退出有什么坑?答案:坑点:不能直接调用run之后强行终止线程,会导致内存泄漏、野指针崩溃;也不能随意退出,容易残留任务。精准退出方案:1.标记线程退出状态,停止向该线程派发新任务2.移除RunLoop中所有Source、Timer事件源3.调用CFRunLoopStop主动终止循环4.置空线程对象,完成释放原理:移除所有事件源后,RunLoop无监听任务,停止循环后线程可正常销毁,无残留问题。六、底层原理与性能优化(高阶面试压轴题)15.讲讲RunLoop和卡顿监控的原理?答案:主线程卡顿本质是UI线程任务耗时过长,RunLoop循环阻塞,可通过RunLoop观察者监控卡顿:核心逻辑:监听BeforeWaiting(即将休眠)和AfterWaiting(唤醒后)两个状态。正常流程:RunLoop快速执行完所有任务,立即进入休眠,两次状态间隔极短。卡顿场景:如果BeforeWaiting到AfterWaiting的时间间隔超过阈值(默认50ms),说明主线程有耗时任务阻塞了RunLoop循环,判定为卡顿,此时可捕获堆栈信息,定位卡顿代码。16.performSelector:withObject:afterDelay:为什么在子线程不执行?怎么解决?答案:不执行原因:该方法底层依赖RunLoop的Source0事件和定时器机制,子线程默认没有开启RunLoop,事件无法被监听和执行,因此方法失效。解决方案:1.手动开启子线程RunLoop,并且添加常驻事件源保活2.替换为GCD延时方法,不依赖RunLoop,子线程可直接执行17.主线程RunLoop什么时候会休眠?什么时候会唤醒?答案:休眠时机:当前RunLoop所有定时器、Source事件全部执行完毕,无任何待处理任务时,立即进入内核休眠状态。唤醒时机:1.定时器任务到期2.触摸、手势等UI

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论