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了没有运行循环的线程, NSTimer
在GCD
运行得并不好。
看看这个问题的其他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”);}];
});