Подтвердить что ты не робот

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 секунд.

4b9b3361

Ответ 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" );  }];

});