Run Loop
运行循环
app 程序只有不停地运行, 才能不断响应用户的操作
Run Loop 两大功能:
- 睡眠中,等待消息
- 处理消息
从睡眠中 -> 处理消息, 需要一个唤醒的过程
1、 讲讲 RunLoop, 项目中有用到吗?
RunLoop 的基本作用:
保持程序的持续运行
节省 CPU 的资源,提高程序的性能 ( 没有事情,就请休眠,不要功耗。有事情,就处理)
2、 RunLoop 内部实现逻辑?
-
Core Foundation 中关于 RunLoop 的 5 个类:
CFRunLoopRef
CFRunLoopModeRef
CFRunLoopSourceRef
CFRunLoopTimerRef
CFRunLoopObserverRef
__CFRunLoop 的数据结构
struct __CFRunLoop {
CFRuntimeBase _base;
pthread_mutex_t _lock; /* locked for accessing mode list */
__CFPort _wakeUpPort; // used for CFRunLoopWakeUp
Boolean _unused;
volatile _per_run_data *_perRunData; // reset for runs of the run loop
pthread_t _pthread;
uint32_t _winthread;
CFMutableSetRef _commonModes;
CFMutableSetRef _commonModeItems;
CFRunLoopModeRef _currentMode;
CFMutableSetRef _modes;
struct _block_item *_blocks_head;
struct _block_item *_blocks_tail;
CFAbsoluteTime _runTime;
CFAbsoluteTime _sleepTime;
CFTypeRef _counterpart;
};
在此一个开发者,有一个学习的氛围跟一个交流圈子特别重要,这有个iOS交流群:642363427,不管你是小白还是大牛欢迎入驻 ,分享BAT,阿里面试题、面试经验,讨论技术!
3、 RunLoop 和线程的关系?
每条线程,都有唯一的一个,与之对应的 RunLoop 对象
runloops[thread] = runloopRunLoop 保存在一个全局的 Dictionary 里,线程作为 Key, RunLoop 作为 Value
线程刚创建时,并没有 RunLoop 对象, RunLoop 会在第一次获取它时,创建
RunLoop 会在线程结束时,销毁线程都没有了,runloop 也就没有意义了
子线程,要什么 runloop?
没有 runloop , 就是命令行,调用一次就完结
有了 runloop, 可以反复休眠、唤醒、处理消息
- 主线程的 RunLoop 已经自动获取 ( 创建 ),子线程默认没有开启 RunLoop
子线程中,获取一下 currentRunLoop, 就创建开启了 RunLoop
CFRunLoopRef CFRunLoopGetCurrent(void) {
CHECK_FOR_FORK();
CFRunLoopRef rl = (CFRunLoopRef)_CFGetTSD(__CFTSDKeyRunLoop);
if (rl) return rl;
// 从这里拿
return _CFRunLoopGet0(pthread_self());
}
进入详情
// should only be called by Foundation
// t==0 is a synonym for "main thread" that always works
CF_EXPORT CFRunLoopRef _CFRunLoopGet0(pthread_t t) {
if (pthread_equal(t, kNilPthreadT)) {
t = pthread_main_thread_np();
}
__CFLock(&loopsLock);
if (!__CFRunLoops) {
__CFUnlock(&loopsLock);
CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, NULL, &kCFTypeDictionaryValueCallBacks);
CFRunLoopRef mainLoop = __CFRunLoopCreate(pthread_main_thread_np());
CFDictionarySetValue(dict, pthreadPointer(pthread_main_thread_np()), mainLoop);
if (!OSAtomicCompareAndSwapPtrBarrier(NULL, dict, (void * volatile *)&__CFRunLoops)) {
CFRelease(dict);
}
CFRelease(mainLoop);
__CFLock(&loopsLock);
}
CFRunLoopRef loop = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(t));
__CFUnlock(&loopsLock);
if (!loop) {
CFRunLoopRef newLoop = __CFRunLoopCreate(t);
__CFLock(&loopsLock);
// 从字典里面,获取 runloop 对象
// __CFRunLoops 字典
// pthreadPointer(t) ,键 key
loop = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(t));
// runloop 对象 loop 不存在,就新建
if (!loop) {
// 字典中,设置
// __CFRunLoops 字典
// pthreadPointer(t),键 key
// newLoop, 值 value
CFDictionarySetValue(__CFRunLoops, pthreadPointer(t), newLoop);
loop = newLoop;
}
// don't release run loops inside the loopsLock, because CFRunLoopDeallocate may end up taking it
__CFUnlock(&loopsLock);
CFRelease(newLoop);
}
if (pthread_equal(t, pthread_self())) {
_CFSetTSD(__CFTSDKeyRunLoop, (void *)loop, NULL);
if (0 == _CFGetTSD(__CFTSDKeyRunLoopCntr)) {
_CFSetTSD(__CFTSDKeyRunLoopCntr, (void *)(PTHREAD_DESTRUCTOR_ITERATIONS-1), (void (*)(void *))__CFFinalizeRunLoop);
}
}
return loop;
}
4、 timer 和 runloop 的关系?
5、 程序中添加每 3 秒响应一次的 NSTimer, 当拖动 tableView 时 timer 可能无法响应,要怎么解决?
6、 RunLoop 是怎么响应用户操作的,具体流程是什么样的?
7、 说说 RunLoop 的几种状态
8、 runloop 的 mode 作用是什么?
推荐:
如果你想一起进阶,不妨添加一下交流群642363427