iOS Runloop面试小笔记

Runloop 是什么?

Runloop 是事件接收和分发机制的一个实现。Runloop 本质是个对象。

Runloop 可以做什么?

可以保活子线程,防止线程在执行完成任务后销毁。

自动释放池。

NSTimer在子线程开启一个定时器,控制定时器在特定模式下执行。

当前线程中有runloop,PerformSelector才能执行。

Runloop 与线程有什么关系?

线程和 RunLoop 之间是一一对应的,其关系是保存在一个 Dictionary 里,key是线程,value是runloop。

子线程刚创建时并没有 RunLoop,必须手动创建。

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

为什么只有主线程的 Runloop 是开启的?

mian()函数中调用UIApplicationMain,会创建一个主线程,用于UI处理,为了让程序可以一直运行并接收事件,所以在主线程中开启一个runloop,让主线程常驻。

为什么只在主线程刷新UI?

因为objc不是一门线程安全的语言所以存在多线程读写不同步的问题,如果使用加锁的方式操作系统开销很大,会耗费大量的系统资源(内存、时间片轮转、cpu处理速度…),加上上面讲到的系统事件的接收处理都在主线程,如果UI异步线程的话,还会存在同步处理事件的问题,所以多点触摸手势等一些事件要保持和UI在同一个线程相对是最优解。

PerformSelector 和 Runloop 的关系

当调用NSObect的performSelector:相关的时候,内部会创建一个timer定时器添加到当前线程的runloop中,如果当前线程没有启动runloop,则该方法不会被调用。

如何启动 Runloop?

// 将接收器放入一个永久循环,在此期间,它处理来自所有连接的输入源的数据。

- (void)run;  // 底层代码 while 调用第三种方式runMode:

// 运行循环直到指定的日期,在此期间它处理来自所有连接的输入源的数据。

- (void)runUntilDate:(NSDate *)limitDate; // 底层代码 while 调用第三种方式runMode:

// R运行一次循环,在指定的日期之前阻止以指定模式输入。

- (BOOL)runMode:(NSRunLoopMode)mode beforeDate:(NSDate *)limitDate;

Runloop 状态总共有几种?

/* Run Loop Observer Activities */
typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
    kCFRunLoopEntry = (1UL << 0),//进入runloop循环
    kCFRunLoopBeforeTimers = (1UL << 1),//即将处理timer事件
    kCFRunLoopBeforeSources = (1UL << 2),//即将处理source事件
    kCFRunLoopBeforeWaiting = (1UL << 5),//即将进入休眠(等待消息唤醒)
    kCFRunLoopAfterWaiting = (1UL << 6),//休眠结束(被消息唤醒)
    kCFRunLoopExit = (1UL << 7),//退出runloop循环
    kCFRunLoopAllActivities = 0x0FFFFFFFU//集合以上所有的状态
};

Runloop 的mode作用是什么?

model 主要是用来指定事件在运行循环中的优先级

NSDefaultRunLoopMode(kCFRunLoopDefaultMode):默认,空闲状态
UITrackingRunLoopMode:ScrollView滑动时
UIInitializationRunLoopMode:启动时
NSRunLoopCommonModes(kCFRunLoopCommonModes):Mode集合
苹果公开提供的 Mode 有两个:

NSDefaultRunLoopMode(kCFRunLoopDefaultMode)
NSRunLoopCommonModes(kCFRunLoopCommonModes)

线程保活有几种方式?

开启该线程的runloop

条件锁

GCD

NSOperation(底层GCD实现)

app如何接收到触摸事件的?

iOS触摸事件全家桶 - 简书

iOS Runloop面试小笔记_第1张图片

通过上图可以看出整个流程就是app启动默认会通过mach port监听端口的方式来接受收SprinaBoard转发来的IOHIDEvent事件。 

你可能感兴趣的:(iOS,ios,面试,objective-c,Runloop)