也来谈谈CFRunLoop(NSRunLoop)

说来,我忘东西还真是飞快。

前一个月自认为把RunLoop研究得比较透彻了,但因为没有在项目中实际使用的缘故,到现在竟然都快忘了,我必须得把它记录下来,以后忘记了我还可以在这里找回来再看看。

 

下面是测试代码:

 

 

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    //这里偷个懒,直接使用performSelectorInBackground来创建一个线程,并执行configRunLoop方法
    [self performSelectorInBackground:@selector(configRunLoop) withObject:nil];
    
    UIButton* __button1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [__button1 setTitle:@"Fire Event" forState:UIControlStateNormal];
    //触发事件启动RunLoop
    [__button1 addTarget:self action:@selector(triggerEvent) forControlEvents:UIControlEventTouchUpInside];
    __button1.frame = CGRectMake(0, 0, 100, 80);
    [self.view addSubview:__button1];
    
    
    UIButton* __button2 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [__button2 setTitle:@"Stop RunLoop" forState:UIControlStateNormal];
    //RunLoop周期完成后自动退出线程
    [__button2 addTarget:self action:@selector(stopRunloop) forControlEvents:UIControlEventTouchUpInside];
    __button2.frame = CGRectMake(110, 0, 120, 80);
    [self.view addSubview:__button2];
}

- (void)stopRunloop{
    _shouldStop = YES;
}

- (void)triggerEvent{
    if (CFRunLoopIsWaiting(_runLoopRef)) {
        NSLog(@"RunLoop 正在等待事件输入");
        //添加输入事件
        CFRunLoopSourceSignal(_source);
        //唤醒线程,线程唤醒后发现由事件需要处理,于是立即处理事件
        CFRunLoopWakeUp(_runLoopRef);
    }else {
        NSLog(@"RunLoop 正在处理事件");
        //添加输入事件,当前正在处理一个事件,当前事件处理完成后,立即处理当前新输入的事件
        CFRunLoopSourceSignal(_source);
    }
}

//此输入源需要处理的后台事件
static void fire(void* info __unused){
    NSLog(@"我现在正在处理后台任务");
    sleep(5);
}

- (void)configRunLoop{
    //这里获取到的已经是某个子线程了哦,不是主线程哦
    _tThread = [NSThread currentThread];
    //这里也是这个子线程的RunLoop哦
    _runLoopRef = CFRunLoopGetCurrent();
    
    bzero(&_source_context, sizeof(_source_context));
    //这里创建了一个基于事件的源
    _source_context.perform = fire;
    _source = CFRunLoopSourceCreate(NULL, 0, &_source_context);
    //将源添加到当前RunLoop中去
    CFRunLoopAddSource(_runLoopRef, _source, kCFRunLoopCommonModes);
    
    
    while (!_shouldStop) {
        NSLog(@"RunLoop 开始运行");
        //每次RunLoop只运行10秒,每10秒做一次检测,如果没有需要处理的后台任务了,就让此线程自己终止,不用暴力Kill
        CFRunLoopRunInMode(kCFRunLoopDefaultMode, 10, NO);
        NSLog(@"RunLoop 停止运行");
    }
    _tThread = nil;
}
 

 

这里是更详细的说明和解释

 

附件是Demo的完整代码

你可能感兴趣的:(IOS)