用GCD运行重复NSTimer?

Shr*_*794 19 objective-c nstimer grand-central-dispatch nsrunloop ios

我想知道为什么当你在GCD块中创建一个重复计时器时它不起作用?

这很好用:

-(void)viewDidLoad{
    [super viewDidLoad];
    [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(runTimer) userInfo:nil repeats:YES];
}
-(void)runTimer{
    NSLog(@"hi");
}
Run Code Online (Sandbox Code Playgroud)

但这项工作:

dispatch_queue_t myQueue;

-(void)viewDidLoad{
    [super viewDidLoad];

    myQueue = dispatch_queue_create("someDescription", NULL);
    dispatch_async(myQueue, ^{
        [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(runTimer) userInfo:nil repeats:YES];
    });
}
-(void)runTimer{
    NSLog(@"hi");
}
Run Code Online (Sandbox Code Playgroud)

Lil*_*ard 59

NSTimers安排在当前线程的运行循环中.但是,GCD调度线程没有运行循环,因此GCD块中的调度计时器不会执行任何操作.

有三种合理的选择:

  1. 找出你想要计划定时器的运行循环,并明确地这样做.使用+[NSTimer timerWithTimeInterval:target:selector:userInfo:repeats:]创建定时器,然后-[NSRunLoop addTimer:forMode:]实际安排它在你想使用的运行循环.这需要在运行循环上设置一个句柄,但是+[NSRunLoop mainRunLoop]如果你想在主线程上执行它,你可以使用它.
  2. 切换到使用基于计时器的调度源.这在GCD感知机制中实现了一个计时器,它将在您选择的队列上以您想要的间隔运行一个块.
  3. dispatch_async()在创建计时器之前显式返回主队列.这相当于使用主运行循环的选项#1(因为它也将在主线程上创建计时器).

当然,这里真正的问题是,为什么要从GCD队列开始创建计时器?