深入理解Runloop(补充)

看完ibreme写的深入理解Runloop(这里),确实非常详细,描述了Runloop概念、原理及主要几个运用库。

这里我再结合几个与Runloop相关的API进行进一步的说明,更方便大家理解:

1、run相关:

在深入理解Runloop中有说到在AFNetWorking中有如下一段代码:

+ (void)networkRequestThreadEntryPoint:(id)__unused object {
    @autoreleasepool {
        [[NSThread currentThread] setName:@"AFNetworking"];
         NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
        [runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
        [runLoop run];//为何这里要run
       //如果这后面还有代码,会执行么?
       NSLog(@"来这里了没")?</span>
    }
}
 
+ (NSThread *)networkRequestThread {
    static NSThread *_networkRequestThread = nil;
    static dispatch_once_t oncePredicate;
    dispatch_once(&oncePredicate, ^{
        _networkRequestThread = [[NSThread alloc] initWithTarget:self selector:@selector(networkRequestThreadEntryPoint:) object:nil];
        [_networkRequestThread start];
    });
    return _networkRequestThread;
}



1、那里为什么是run,不是runUntilDate等?

这里主要明白这几个api的区别,

run:是让runloop无限的运行下去,但是这里的无限运行下去有个条件,首先这个app当然是还在运行,如果app关了自然不在了,其次,必须至少有一个observer或source或timer(注意这里是或,也就有其中一个也可以)。所以这里为什么上面的例子中加入NSMachPort,虽然这个port没有处理实际的事件。

runUntilDate:这就是让这个runloop最多活不过这个date参数,如果到期了,runloop就退出。但是同样想让runloop进入运行状态,在执行这个api之前,必须往loop里添加至少一

    个observer或source或timer。

    runMode:beforeDate:从字面理解就是,在xx日期前运行xx模式,这个接口很特别,它有两个退出条件,如果在date前它处理了一个消息(如果是只有重复的timer,会一直到传入的date,但期间如果处理了其他任何其他消息,则退出),它会退出,如果在date前,即使时间还没发生(如NSTimer还没到触发点),它会退出。


    所以从AFNetWorking的使用需求上,因为网络请求贯穿整个APP生命周期,所以这里用run是最合适的。


    2、后面的打印代码执行了没?

    因为我们已知runloop的run相关api是让runloop进入一个do{}while()循环,只要不到退出条件,它就会处于循环中,因此可以知道后面的代码是没有执行的,但是一旦loop退出循环,代码就会继续执行,当执行到最后一行后,线程结束并销毁。


    2、NSTimer相关

    我们一般用两种方式方式初始化NSTimer,一种是直接sheduledTimer,一种是alloc后,再把timer加到runloop里,其实两种方式是一样的。就是把Timer加入到当前runloop或指定runLoop,一旦到达指定时间,runloop就处理对应事件,但是如果当timer指定时间到达,但当前runloop还是处理着其他消息,那timer就会等runloop处理完其他消息,timer被延时操作,但是timer可以设置容忍度T,因此如果处理该timer的时间A,离预计的timer事件B,大于T,也即A>B+T,这个timer事件就会被抛弃。


    这里因此有一个问题,timer是加到当前runloop或指定runloop,我们知道,除主线程外,其他线程默认是没有runloop开启的。因此如果你在辅助线程中使用timer,必须要手动让这个loop跑起来。

    [runLoop  run]

    3、performSelector:delay:

    performSelector:delay:与timer类似,就是系统会生成一个定时器,然后添加到当前runloop中,因此具体操作需要与NSTimer一致。



    4、dispatch_after

    dispatch本身就是消息队列(我们可以认为是就是一个已经开启的runloop),与runloop不一样,因此不会像timer一样,需要考虑当前线程是否有runloop,以及runloop是否运行。



    5、总结

    NSThread * thread = [[NSThread alloc] initWithTarget:self selector:@selector(doThread:) object:nil];
    
    [thread start];
    
    
    
    -(void)doThread:(id)ni
    {
        //这个方法在
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [self doSm1];
        });
        [self performSelector:@selector(doSm2) withObject:nil afterDelay:2];
        
        [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(doSm3) userInfo:nil repeats:NO];
    }


    上面代码中,哪些方法会执行呢?


    结果:1执行,2、3不执行。



    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值