NSTimer需要我将它添加到runloop

我想知道是否有人可以解释为什么调度回主队列,并创build一个重复的NSTimer我不得不把它添加到运行环路太火了? 即使在使用performselectorOnMainThread我仍然需要将它添加到RUN LOOP才能启动它。

下面是我的问题的一个例子:

 #define queue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) #define mainqueue dispatch_get_main_queue() - (void)someMethodBeginCalled { dispatch_async(queue, ^{ int x = 0; dispatch_async(mainqueue, ^(void){ if([_delegate respondsToSelector:@selector(complete:)]) [_delegate complete:nil]; }); }); } - (void)compelete:(id)object { [self startTimer]; //[self performSelectorOnMainThread:@selector(startTimer) withObject:nil waitUntilDone:NO]; } - (void)startTimer { NSTimer timer = [NSTimer timerWithTimeInterval:3 target:self selector:@selector(callsomethingelse) userInfo:nil repeats:YES]; //NSDefaultRunLoopMode [[NSRunLoop currentRunLoop] addTimer:_busTimer forMode:NSRunLoopCommonModes]; } 

编辑:我相信我很难说这个问题。 我想知道为什么 [[NSRunLoop currentRunLoop] addTimer:_busTimer forMode:NSRunLoopCommonModes]; 如果我调用someMethodBeginCalled则在startTimer是必需的。 如果我不包括该行,定时器不会触发。

例如,如果我从viewDidLoad调用startTimer ,我可以删除NSRunLoop行,计时器每60秒触发一次。

你总是可以使用这个方法:

NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(getBusLocation) userInfo:nil repeats:YES];

这将为您节省一条线,因为它会自动将其添加到运行循环中。

下面是如何将NSTimer添加到runloop:

 NSRunLoop *runLoop = [NSRunLoop currentRunLoop]; [runLoop addTimer:timer forMode:NSDefaultRunLoopMode]; 

因为,正如文件所说:

定时器与运行循环一起工作。 要有效地使用定时器,你应该知道如何运行循环 – 参见NSRunLoop和Threading Programming Guide。 请特别注意,运行循环会保留它们的定时器,因此在将其添加到运行循环后,您可以释放一个定时器。

这是苹果在为NSTimer编写代码时做出的一个devise决定(我相信他们有充足的理由这么做),我们无能为力。 这真的很累吗?

就像@sosborn所说的那样, NSTimer依赖于NSRunLoop ,由于GCD队列创build了没有运行循环的线程, NSTimerGCD运行得并不好。

看看这个问题的其他StackOverflow问题: 在GCD串行队列上安排和无效NSTimers是否安全?

为了解决这个问题,我实现了MSWeakTimer : https : //github.com/mindsnacks/MSWeakTimer (并且在最后的WWDC上由一个libdispatch工程师检查了实现)!

将计时器添加到runloop在我的情况下不起作用。 我不得不在主线程上创build定时器。 我在MultipeerConnectivity委托中做了这个线程创build。

  dispatch_async(dispatch_get_main_queue(), ^{ self.timer = [NSTimer scheduledTimerWithTimeInterval:self.interval invocation: self.invocation repeats:YES]; }); 

定时器方法不会被调用,因为GCD队列创build没有运行循环的线程

dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,0),^ {[NSTimer scheduledTimerWithTimeInterval:1重复:是阻止:^(NSTimer * _Nonnull定时器){NSLog(@“定时器方法从GCD主队列”);}];

});

但是当在主队列上调度时,timer方法将被调用,因为它将被添加到主线程run loop中。

dispatch_get_main_queue(),^ {[NSTimer scheduledTimerWithTimeInterval:1 repeat:YES block:^(NSTimer * _Nonnull timer){NSLog(@“Timer method from GCD main queue”);}];

});