RunLoop
- RunLoop内部实现就是do-while循环,在这循环之内不断地处理各种任务(Source、Timer、Observer)
- 一个线程对应一个RunLoop,主线程的RunLoop默认已启动,子线程RunLoop得手动创建并调用run方法
- RunLoop只能选择一个Mode启动,如果当前Mode中没有Sourcr、Timer,那么就直接退出RunLoop
RunLoop运行流程
- 通知Observer:即将进入Loop
- 通知Observer:将要处理Timer
- 通知Observer:将要处理Source0
- 处理Source0
- 如果有Source1,跳到第九步
- 通知Observer:线程即将休眠
- 休眠,等待唤醒
- 通知Observer:线程刚被唤醒
- 处理唤醒时收到的消息,之后跳回2
- 通知Observer:即将退出Loop
CFRunLoopModeRef
- kCFRunLoopDefaultMode
- App的默认Mode,通常主线程是在这个Mode下运行
- UITrackingRunLoopMode
- 界面跟踪Mode,用于ScrollView追踪触摸滑动,保证界面滑动时不受其他Mode影响
- UIInitializationRunLoopMode
- 在刚启动App时进入的第一个Mode,启动完成后就不再使用
- GSEventReceiveRunLoopMode
- kCFRunLoopCommonModes
CFRunLoopSourceRef
- Source0:非基于Port
- Source1:基于Port
CFRunLoopObserverRef
CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
switch (activity) {
case kCFRunLoopEntry:
NSLog(@"即将进入RunLoop");
break;
case kCFRunLoopBeforeTimers:
NSLog(@"即将处理Timer事件");
break;
case kCFRunLoopBeforeSources:
NSLog(@"即将处理TSources事件");
break;
case kCFRunLoopBeforeWaiting:
NSLog(@"即将进入休眠");
break;
case kCFRunLoopAfterWaiting:
NSLog(@"RunLoop被唤醒");
break;
case kCFRunLoopExit:
NSLog(@"RunLoop退出");
break;
default:
break;
}
});
CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);
常驻子线程
- 开启一个子线程
- 创建子线程的RunLoop,并设置RunLoop一个Source或者Timer,否则RunLoop创建即退出
- 开启RunLoop run
#import "ViewController.h"
@interface ViewController ()
@property(nonatomic, strong)NSThread *thread;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (IBAction)createThread {
self.thread = [[NSThread alloc] initWithTarget:self selector:@selector(create) object:nil];
[self.thread start];
}
- (void)create{
NSLog(@"%s", __func__);
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addPort:[NSPort port] forMode:NSDefaultRunLoopMode];
[runLoop run];
}
- (IBAction)executeTask:(id)sender {
[self performSelector:@selector(task) onThread:self.thread withObject:nil waitUntilDone:YES];
}
- (void)task{
NSLog(@"%@", [NSThread currentThread]);
}
@end
关于自动释放池
- 第一次创建:启动RunLoop
- 最后一次销毁:RunLoop退出的时候
- 其他时候的创建和销毁:当RunLoop即将睡眠的时候销毁之前的释放池,重新创建一个新的
网友评论