新建 NSThread CFRunLoop
2019-08-20 本文已影响0人
yulekwok
NSThread * pthread = [[NSThread alloc] initWithBlock:^{
NSLog(@"begin----");
// 创建上下文(要初始化一下结构体)
CFRunLoopSourceContext context = {0};
// 创建source
CFRunLoopSourceRef source = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context);
// 往Runloop中添加source
CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode);
// 销毁source
CFRelease(source);
// 启动
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1.0e10, false);
// while (weakSelf && !weakSelf.isStopped) {
// // 第3个参数:returnAfterSourceHandled,设置为true,代表执行完source后就会退出当前loop
// CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1.0e10, true);
// }
}];
CFRunLoopStop(CFRunLoopGetCurrent());
runLoop 的工作流程
序号 | 说明 | 对应的方法 在命令行bt 可以打印堆栈信息 |
---|---|---|
1 | 通知Observers:进入Loop | CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION |
2 | 通知Observers:即将处理Timers | |
3 | 通知Observers:即将处理Sources | |
4 | 处理Blocks | CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK |
5 | 处理Source0(可能会再次处理Blocks) | CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION |
6 | 如果存在Source1,就跳转到第8步 | |
7 | 通知Observers:开始休眠(等待消息唤醒) | |
8 | 通知Observers:结束休眠(被某个消息唤醒) | |
1>处理Timers | CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION | |
2>处理GCD Async To Main Queue | CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE (大部分情况下GCD自己处理 这种情况下才会 dispatch_async(dispatch_get_main_queue(), ^{})) | |
3>处理Source1 | CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION | |
9 | 处理Blocks | CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK |
10 | 根据前面的执行结果,决定如何操作 | |
1>回到第2步 | ||
2>退出Loop | ||
11 | 通知Observers:退出RunLoop |
typedef struct __CFRunLoop * CFRunLoopRef;
struct __CFRunLoop {
pthread_t _pthread;
CFMutableSetRef _commonModes;
CFMutableSetRef _commonModeItems;
CFRunLoopModeRef _currentMode;
CFMutableSetRef _modes;
};
typedef struct __CFRunLoopMode *CFRunLoopModeRef;
struct __CFRunLoopMode {
CFStringRef _name;
CFMutableSetRef _sources0;
CFMutableSetRef _sources1;
CFMutableArrayRef _observers;
CFMutableArrayRef _timers;
};
runLoop | runLoop |
---|---|
Mode | Mode |
source0 | source0 |
source1 | source1 |
observers | observers |
timers | timers |
mode | Action |
---|---|
source0 | 1. 触摸事件 2. performSelector:onThread: |
source1 | 1.基于Port的线程间通信 2. 系统事件捕捉 |
Timers | 1.NSTimer 2. performSelector: withObject: afterDelay: |
Observers | 1. 用于监听RunLoop的状态 2. UI刷新(BeforeWating) 3. AutoRelease Pool |
/* Run Loop Observer Activities */
typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
kCFRunLoopEntry = (1UL << 0), // 即将进入Loop
kCFRunLoopBeforeTimers = (1UL << 1), // 即将处理Timer
kCFRunLoopBeforeSources = (1UL << 2), // 即将处理Source
kCFRunLoopBeforeWaiting = (1UL << 5), // 即将进入休眠
kCFRunLoopAfterWaiting = (1UL << 6), // 即将从休眠中唤醒
kCFRunLoopExit = (1UL << 7), //即将退出Loop
kCFRunLoopAllActivities = 0x0FFFFFFFU
};
添加监听
void observerRunLoopActivity(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info)
{
CFRunLoopMode mode = CFRunLoopCopyCurrentMode(CFRunLoopGetCurrent());
NSLog(@"mode == %@", mode);
switch (activity) {
case kCFRunLoopEntry: {
NSLog(@"kCFRunLoopEntry");
}
break;
case kCFRunLoopBeforeTimers: {
NSLog(@"kCFRunLoopBeforeTimers");
}
break;
case kCFRunLoopBeforeSources: {
NSLog(@"kCFRunLoopBeforeSources");
}
break;
case kCFRunLoopBeforeWaiting: {
NSLog(@"kCFRunLoopBeforeWaiting");
}
break;
case kCFRunLoopAfterWaiting: {
NSLog(@"kCFRunLoopAfterWaiting");
}
break;
case kCFRunLoopExit: {
NSLog(@"kCFRunLoopExit");
}
break;
default:
break;
}
CFRelease(mode);
}
- (void)createObserver1 {
// 创建observer
CFRunLoopObserverRef observer = CFRunLoopObserverCreate(kCFAllocatorDefault, kCFRunLoopAllActivities, YES, 0, observerRunLoopActivity, NULL);
// 添加observer 到runloop中
CFRunLoopAddObserver(CFRunLoopGetMain(), observer, kCFRunLoopCommonModes);
// 释放observer
CFRelease(observer);
}
- (void)createObserver2 {
CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(kCFAllocatorDefault, kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
switch (activity) {
case kCFRunLoopEntry: {
NSLog(@"kCFRunLoopEntry");
}
break;
case kCFRunLoopBeforeTimers: {
NSLog(@"kCFRunLoopBeforeTimers");
}
break;
case kCFRunLoopBeforeSources: {
NSLog(@"kCFRunLoopBeforeSources");
}
break;
case kCFRunLoopBeforeWaiting: {
NSLog(@"kCFRunLoopBeforeWaiting");
}
break;
case kCFRunLoopAfterWaiting: {
NSLog(@"kCFRunLoopAfterWaiting");
}
break;
case kCFRunLoopExit: {
NSLog(@"kCFRunLoopExit");
}
break;
default:
break;
}
});
CFRunLoopAddObserver(CFRunLoopGetMain(), observer, kCFRunLoopCommonModes);
CFRelease(observer);
}