NSTimer требует от меня добавить его в runloop
Мне интересно, может ли кто-нибудь объяснить, почему отправка обратно в основную очередь и создание повторяющегося NSTimer
Мне нужно добавить его в RUN LOOP, чтобы он тоже был огнем? Даже при использовании 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];
}
EDIT:
Полагаю, я сформулировал этот вопрос очень плохо. Я хотел бы знать , почему [[NSRunLoop currentRunLoop] addTimer:_busTimer forMode:NSRunLoopCommonModes];
необходим в startTimer
, если я вызываю someMethodBeginCalled
. Если я не включаю эту строку, таймер не срабатывает.
Если я вызываю startTimer
из viewDidLoad
, например, я могу удалить строку NSRunLoop
, и таймер будет срабатывать каждые 60 секунд.
Ответы
Ответ 1
Вы всегда можете использовать этот метод:
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(getBusLocation) userInfo:nil repeats:YES];
Это сохранит вам строку, так как она автоматически добавит ее в цикл запуска.
Ответ 2
А вот как добавить NSTimer
в runloop:
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:timer forMode:NSDefaultRunLoopMode];
Ответ 3
Потому что, как docs говорят:
Таймеры работают вместе с циклами запуска. Чтобы эффективно использовать таймер, вы должны знать, как работают циклы циклов - см. NSRunLoop и Руководство по программированию потоков. Обратите внимание, в частности, что циклы запуска сохраняются их таймеры, поэтому вы можете выпустить таймер после того, как вы добавили его в цикл выполнения.
Это дизайнерское решение, которое Apple сделала, когда написала код для NSTimer (и я уверен, что у них есть все основания для этого), и мы ничего не можем сделать, чтобы обойти его. Неужели это так обременительно?
Ответ 4
Как и @sosborn, NSTimer
зависит от NSRunLoop
s, а так как очереди GCD создают потоки, которые не имеют циклов запуска, NSTimer
плохо работает с GCD
.
Проверьте этот другой вопрос StackOverflow по этому вопросу: Можно ли планировать и отменять NSTimers в последовательной очереди GCD?
Чтобы решить эту проблему, я внедрил MSWeakTimer
: https://github.com/mindsnacks/MSWeakTimer (и была выполнена проверка, установленная инженером libdispatch последним WWDC!)
Ответ 5
Добавление таймера в runloop не помогло мне. Мне нужно было создать таймер в основном потоке. Я делал это создание потока в делегате MultipeerConnectivity.
dispatch_async(dispatch_get_main_queue(), ^{
self.timer = [NSTimer scheduledTimerWithTimeInterval:self.interval invocation: self.invocation repeats:YES];
});
Ответ 6
Метод таймера не будет вызываться, поскольку очереди GCD создают потоки, которые не имеют циклов запуска
dispatch_async (dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ { [NSTimer scheduleTimerWithTimeInterval: 1 повтор: блок YES: ^ (NSTimer * _Nonnull timer) { NSLog (@ "Метод таймера из главной очереди GCD" ); }];
});
Однако при отправке в основную очередь будет вызываться метод таймера, поскольку он будет добавлен в основной цикл выполнения потоков.
dispatch_async (dispatch_get_main_queue(), ^ { [NSTimer scheduleTimerWithTimeInterval: 1 повтор: блок YES: ^ (NSTimer * _Nonnull timer) { NSLog (@ "Метод таймера из главной очереди GCD" ); }];
});