RunLoop的底层源码: Source Browser
然后找到CFRunLoop.h和CFRunLoop.c这两个文件就是RunLoop的底层源码了
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; //一线程对应一个runloop所以这是对应的线程
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;
};
这就是runloop对象的源代码了,基本很多看名字都能看懂,比如runtime,运行时间,sleepTime休眠时间,就不一一赘述了,核心的是_currentModel和_modes
typedef struct __CFRunLoopMode *CFRunLoopModeRef;
struct __CFRunLoopMode {
CFRuntimeBase _base;
pthread_mutex_t _lock; /* must have the run loop locked before locking this */
CFStringRef _name;
Boolean _stopped;
char _padding[3];
CFMutableSetRef _sources0;
CFMutableSetRef _sources1;
CFMutableArrayRef _observers;
CFMutableArrayRef _timers;
CFMutableDictionaryRef _portToV1SourceMap;
__CFPortSet _portSet;
CFIndex _observerMask;
#if USE_DISPATCH_SOURCE_FOR_TIMERS
dispatch_source_t _timerSource;
dispatch_queue_t _queue;
Boolean _timerFired; // set to true by the source when a timer has fired
Boolean _dispatchTimerArmed;
#endif
#if USE_MK_TIMER_TOO
mach_port_t _timerPort;
Boolean _mkTimerArmed;
#endif
#if DEPLOYMENT_TARGET_WINDOWS
DWORD _msgQMask;
void (*_msgPump)(void);
#endif
uint64_t _timerSoftDeadline; /* TSR */
uint64_t _timerHardDeadline; /* TSR */
};
然后看下model声明的地方,有
CFMutableSetRef _sources0;
CFMutableSetRef _sources1;
CFMutableArrayRef _observers;
CFMutableArrayRef _timers;
所以面试题:RunLoop 和RunLoopModel和 RunLoopSource,RunLoopObserver,RunLoopTimer的关系是?
答案是,RunLoop可以有多个运行模式,但是只会有一个是启用状态,也就是_currentMode而每个模式又有多个source,observer,timer负责具体的工作,而同时不同组别的source,observer,timer之间其实是互不干扰的,当转换Mode的时候新的Mode会做自己的事情,以前的事情则会暂时放下,比如如果一个界面有计时器操作和滚动页,但当tableview滚动的时候,计时器就会停止,当tableview滚动停止,计时器重新恢复,便是这个原因