顾名思义, Runloop就是运行循环, 在程序运行过程当中循环作一些事情bash
应用范畴网络
一个OC程序, main
函数是这样的app
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
复制代码
Runloop
, main
函数返回0
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char * argv[]) {
@autoreleasepool {
return 0;
}
}
复制代码
Runloop
的伪代码, 以下图所示do-while
是一个死循环, 当没有任何消息发生的时候, 程序处于睡眠状态等待消息发生RunLoop的基本做用
保持程序的持续运行
处理App中的各类事件(好比触摸事件、定时器事件等)
节省CPU资源,提升程序性能:该作事时作事,该休息时休息
......
复制代码
Foundation
和Core Foundation
来获取RunLoop
[NSRunLoop currentRunLoop];
复制代码
[NSRunLoop mainRunLoop];
复制代码
CFRunLoopGetCurrent()
复制代码
CFRunLoopGetMain()
复制代码
CFRunLoopRef
CFRunLoopModeRef
CFRunLoopSourceRef
CFRunLoopTimerRef
CFRunLoopObserverRef
复制代码
CFRunLoopRef
实际类型是__CFRunLoop
typedef struct CF_BRIDGED_MUTABLE_TYPE(id) __CFRunLoop * CFRunLoopRef;
struct __CFRunLoop {
pthread_t _pthread;
CFMutableSetRef _commonModes;
CFMutableSetRef _commonModeItems;
CFRunLoopModeRef _currentMode;
CFMutableSetRef _modes;
};
复制代码
_modes
中存放的是CFRunLoopModeRef
类型数据, 其中就有_currentMode
, 只不过_currentMode
是当前使用的mode
函数
CFRunLoopModeRef
的结构以下oop
typedef struct __CFRunLoopMode *CFRunLoopModeRef;
struct __CFRunLoopMode {
CFStringRef _name;
CFMutableSetRef _sources0;
CFMutableSetRef _sources1;
CFMutableArrayRef _observers;
CFMutableArrayRef _timers;
};
复制代码
_sources0
和_sources1
是CFRunLoopSourceRef
类型数据_observers
是CFRunLoopObserverRef
类型数据_timers
是CFRunLoopTimerRef
类型数据CFRunLoopModeRef
表明RunLoop
的运行模式RunLoop
包含若干个Mode
,每一个Mode
又包含若干个Source0/Source1/Timer/Observer
RunLoop
启动时只能选择其中一个Mode
,做为currentMode
Mode
,只能退出当前Loop
,再从新选择一个Mode
进入
Source0/Source1/Timer/Observer
能分隔开来,互不影响Mode
里没有任何Source0/Source1/Timer/Observer
,RunLoop
会立马退出kCFRunLoopDefaultMode
(NSDefaultRunLoopMode
): App
的默认Mode
,一般主线程是在这个Mode
下运行UITrackingRunLoopMode
: 界面跟踪 Mode
,用于 ScrollView
追踪触摸滑动,保证界面滑动时不受其余 Mode
影响Source0
处理的RunLoop
添加Observer
的方式监听RunLoop
的状态, 使用下面这个函数/** 给RunLoop添加Observer @param rl 目标RunLoop @param observer 须要添加的Observer @param mode 监听状态 */
void CFRunLoopAddObserver(CFRunLoopRef rl, CFRunLoopObserverRef observer, CFRunLoopMode mode);
复制代码
Observer
/**
建立Observer
@param allocator 分配器
@param activities 须要监听的状态
@param repeats 是否重复监听
@param order 顺序
@param callout 回调函数
@param context 附加对象
@return 建立好的Observer
*/
CF_EXPORT CFRunLoopObserverRef CFRunLoopObserverCreate(CFAllocatorRef allocator, CFOptionFlags activities, Boolean repeats, CFIndex order, CFRunLoopObserverCallBack callout, CFRunLoopObserverContext *context);
复制代码
RunLoop
的状态有下面几种/* Run Loop Observer Activities */
typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
kCFRunLoopEntry = (1UL << 0),
kCFRunLoopBeforeTimers = (1UL << 1),
kCFRunLoopBeforeSources = (1UL << 2),
kCFRunLoopBeforeWaiting = (1UL << 5),
kCFRunLoopAfterWaiting = (1UL << 6),
kCFRunLoopExit = (1UL << 7),
kCFRunLoopAllActivities = 0x0FFFFFFFU
};
复制代码
Observer
, 并将其添加到Runloop
中, 监听屏幕点击事件RunLoop
的状态, 当最后没有事件时, Runloop
进入睡眠状态sources
状态, 而后执行点击事件监听UITextView
的滚动, 查看RunLoop
的currentMode
性能
建立Observer
的另外一种方式, 使用block
监听RunLoop
状态ui
view
上添加一个UITextView
UITextView
, 有以下打印kCFRunLoopDefaultMode
, 进入UITrackingRunLoopMode
UITrackingRunLoopMode
, 进入kCFRunLoopDefaultMode