废话:很久没有写东西了,以前写的东西觉得不太严谨还删除了一些文章,以免给大家误导。写这个文章原因是因为我在面试的时候遇到的一个问题,理解了一些就想分享出来。
正经:当时的问题是在并发异步的多线程执行任务,[self performSelector:@selector(print) withObject:nil afterDelay:0];这个方法会不会执行print,觉得码字可能说不清楚,还是贴代码如图1
这段代码的打印的顺序应该是什么呢?很多朋友应该都知道,没错是 3 1如图2。至于为什么先打3后打1 不知道的朋友可以看看GCD并发队列和异步函数的使用问题,并不会打印2。这个原因是因为我们使用的并发加异步的方式会开启子线程,而[self performSelector:@selector(print) withObject:nil afterDelay:0];是底层runloop的添加timer方式,又因为子线程的runloop默认是没有开启的,所有并不会执行print方法。
到这里该有朋友问了那如何才能走print方法,其实我们只要把[self performSelector:@selector(print) withObject:nil afterDelay:0];方法的 afterDelay去掉就能执行print,废话不多说,代码跑一遍。看图3。
这是因为去掉afterDelay的方法就变成了NSObject消息发送机制了,跟我们平时调用方法一样,会被直接调用。
那有人会问了,你这是改动了方法之后才起到效果的,如果在不改[self performSelector:@selector(print) withObject:nil afterDelay:0];的方法情况下,如何执行print呢?其实也是有方法的,上面我也说到了,其实是因为这个方法是runloop的添加timer,那既然是因为没有开启runloop,那我们开启不就好了。
跑一下看看:图5
居然没有打印2?为什么呢?我不是启动了runloop了吗? 带着疑惑我打印了下runloop。图6
我发现runloop的source0 source1 observers 以及timers全都是null,那就知道为什么了, 其实只是我们开启runloop的地方错了,需要放到[self performSelector:@selector(print) withObject:nil afterDelay:0]之后去开启,这样才有timers,如下两图
现在就有了timer,所以print也就正常打印了,如图9
结语:希望对这些还不明白的同学有所帮助。每天学习一点 进步一点 学无止境,还有很多的知识没有掌握,需要我们自己不断的去探索学习。加油,所有iOSer!!!