美文网首页ios性能优化程序员iOS
performSelector afterDelay在子线程上调

performSelector afterDelay在子线程上调

作者: PotterSun | 来源:发表于2015-07-13 17:53 被阅读3487次

    平时我们想延迟一段代码的运行,最简单的方法就是使用 performSelector afterDelay,但是你有没有发现在子线程中调用这个方法,有时候延时执行的代码并没有走,这是为什么呢?

    我们先看一下下面的例子:

    我们在.m文件里面加入如下方法

       - (void)viewDidLoad {
            [super viewDidLoad];
            NSThread * thread = [[NSThread alloc] initWithTarget:self selector:@selector(threadRun) object:nil];
            [thread start];
    }

    - (void)threadRun
    {
        [self performSelector:@selector(delayTest) withObject:nil afterDelay:0.2];     //不会调用
        [self performSelector:@selector(noDelayTest) withObject:nil];                       //会调用
    }

    - (void)delayTest
    {
        NSLog(@"this is delayTest");
    }

    - (void)noDelayTest
    {
        NSLog(@"this is noDelayTest");
    }

    我们发现,在0.2秒之后,delayTest方法并没有走,而如果我们没有使用afterDelay的noDelayTest 方法却直接调用了,这是为什么呢?

    其实performSelector 方法相当于告诉当前线程去直接去调用noDelayTest方法,noDelayTest方法当然会被调用,

    而performSelector afterDelay 相当于 告诉当前线程 用当前线程的定时器去调用delayTest方法,但是我们知道,在子线程中,默认是没有定时器的,所以delayTest方法将没有被调用的机会.

    解决办法

    使用dispatch_after代替performSelector afterDelay,具体如下

    - (void)threadRun
    {
        //会调用
        dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 0.2*NSEC_PER_SEC);
        dispatch_after(time, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            [self delayTest];
        });
    }

    结论

     1.performSelector 如果不使用延时,程序会再子线程上直接调用该方法,方法会被调用
     2.如果使用延时,在子线程中方法不会被调用,因为该方法等待定时器去调用,而该子线程中没有定时器,所以不会调用
     3.解决2的方法就是使用dispatch_after里面会有一个定时器,来调用方法

    相关文章

      网友评论

      • 狂风被雨淋:你这是治标不治本吧,这样也不是在当前线程执行,而是换到了一个global queue里面执行。把当前线程的runloop开启就可以了。
        云天涯丶:@Liberalism 直接在子线程里方法里开启runloop就可以了(之前我加了port,发现多余了,performSelector:withObject:afterDelay: 默认开启了timer并加入runloop)
        Liberalism:直接添加 Runloop 并执行 Run 是不起作用的,这里涉及到 timer,我在测试过程中想添加一个,但是没有成功。
      • b40c0b35dc9b:学习了
      • 笑谈红尘乱离人:不是子线程没有定时器,而是子线程没有一个默认运行的runloop
      • IOS馄饨:原来是子线程里没有定时器 :unamused:
        Liberalism:@Liberalism 是默认没有,可以懒加载出来
        Liberalism:子线程中没有 Runloop
      • Auditore:GCD还是好用啊
      • d26158d9d727: 请教,如何才能在子线程中使用performselector: afterDelay 这个方法呢,可以给子线程添加定时器么
        HoFie:@Liberalism 把[[NSRunLoop currentRunLoop] run]添加到performselector: afterDelay之后,就会执行,如果你设置延迟执行1s,那么子线程就会阻塞1秒。
        Liberalism:@无4名 直接添加 Runloop 并执行 Run 是不起作用的,这里涉及到 timer,我在测试过程中想添加一个,但是没有成功。
        eee3299c3391:@小小零号 开启子线程的runloop

      本文标题:performSelector afterDelay在子线程上调

      本文链接:https://www.haomeiwen.com/subject/qnpsfttx.html