Runloop

2016-10-13  本文已影响0人  彼岸的黑色曼陀罗

Runloop

Runloop与线程

获得Runloop对象

Runloop相关类

CFRunLoopModeRef

CFRunLoopModeRef和NSTimer

GCD中的定时器(掌握)

dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE__TIMER,0,0,dispatchQueue)
- 第一个参数:要创建的是一个定时器 
- 第二个参数:默认总是传0,描述信息
- 第三个参数:默认总是传0,
- 第四个参数:队列,并发队列(全局),决定代码块(dispatch_source_set_event_handler)在哪个线程中调用(主队列+主线程)
dispatch_source_set_timer(timer,DISPATCH_TIME_NOW,intervalInSeconds *NSEC_PER_SEC,leewayInSeconds *NSEC_PER_SEC)
- 第一个参数:定时器对象
- 第二个参数:定时器开始计时的时间(开始时间)
    - 怎么修改开始时间?
        - dispatch_time_t t = dispatch_time(DISPATCH_TIME_NOW,延迟时间2.0*NSEC_PER_SEC)  
- 第三个参数:设置间隔时间 GCD的时间单位:纳秒
- 第四个参数:精准的,0表示绝对精准
dispatch_source_set_event_handler(timer,^{}) 

RunloopSourceRef

RunloopObserverRef

runloop的运行流程

代码模拟runloop死循环


void msg(int n)
{
    NSLog(@"runloop被唤醒");
    NSLog(@"runloop处理%zd事件",n);
}
int main(int argc, const char * argv[]) {
    @autoreleasepool {
       
        NSLog(@"runloop启动了");
        do {
            
            NSLog(@"runloop即将处理timer事件");
            NSLog(@"runloop即将处理source0事件");
            NSLog(@"source1事件");
            NSLog(@"runloop询问:还有事件需要我处理吗?");
            NSLog(@"runloop计入到休眠状态");
            
            int number = 0;
            scanf("%zd",&number);
            msg(number);
            
            
        } while (1);
    }
    return 0;
}

runloop的应用

-(void)test1
{
     [NSThread detachNewThreadSelector:@selector(task) toTarget:self withObject:nil];
}

-(void)task
{
    [self.imageView performSelector:@selector(setImage:) withObject:[UIImage imageNamed:@"Snip20160713_9"] afterDelay:3.0];
    //运行模式启动之后,判断有一个selector事件,runloop才能够开启
    NSRunLoop *runloop = [NSRunLoop currentRunLoop];
    [runloop run];
    
    NSLog(@"+++++");
}
//需要进行线程间通信,否则会报错
//创建线程,执行任务
- (IBAction)createNewThreadBtnClick:(id)sender {
    
    //01 创建线程,执行任务
    //因为要拿到线程对象,所以用NSThread创建线程
    NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(run1) object:nil];
    
    //02 执行任务
    [thread start];
    
    self.thread = thread;
}


//继续执行任务
- (IBAction)goOnBtnClick:(id)sender {
    
    /*
    self.thread 任务执行完毕,已经进入到死亡状态|但是还没有被释放
    程序崩溃报错:attempt to start the thread again 
    [self.thread start];❎不能尝再次开启线程
    怎么让任务执行不完呢?在run1方法里搞一个死循环?这样做线程不会死,但是不会执行任务2
    正确做法:在run1方法里面开启一个runloop
    */
    
    //让之前创建的线程继续执行
    [self performSelector:@selector(run2) onThread:self.thread withObject:nil waitUntilDone:YES];
    
}

-(void)run1
{
    NSLog(@"run1---%@",[NSThread currentThread]);
    
    /*
    do {
        NSLog(@"-%@",[NSThread currentThread]);
    } while (1);
     */
    
    //001 获得当前线程对应的runloop对象
    NSRunLoop *currentRunloop = [NSRunLoop currentRunLoop];
    
    //002 为runloop添加input soucre或者是timer souce ,为了让运行模式不为空,否则不能开启runloop
    //基于端口的事件
    //好处:不需要调用方法,开发中常用
    [currentRunloop addPort:[NSPort port] forMode:NSDefaultRunLoopMode];
    
    //Perform事件
    //存在的问题:3.0s之后就退出了,开发中一般不用selector方法
    //[self performSelector:@selector(run3) withObject:nil afterDelay:3.0];
    //NSTimer事件
    //[NSTimer scheduledTimerWithTimeInterval:3.0 target:self selector:@selector(timerTest) userInfo:nil repeats:YES];
    
    //003 启动runloop
    //runUntilDate |run 内部都指定了运行模式为默认
    [currentRunloop run];
    //[currentRunloop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:10000000]];
    
    NSLog(@"_______end____");//验证runloop是否开启了,打印(没有开启runloop)
    
}

-(void)run2
{
    NSLog(@"run2---%@",[NSThread currentThread]);
}
-(void)run3
{
    NSLog(@"run3---%@",[NSThread currentThread]);
}

-(void)timerTest
{
    NSLog(@"timer---");
}


runloop常见面试题

总结:

上一篇 下一篇

猜你喜欢

热点阅读