Не работает вызов метода каждую секунду

#objective-c #gnustep

#цель-c #gnustep #objective-c

Вопрос:

Я пытаюсь запланировать вызов метода GNUstep Objective-C, чтобы он выполнялся каждую секунду в течение переменного количества секунд. Я пытаюсь использовать NSTimer для планирования вызова метода, но метод-обработчик никогда не вызывается.

Вот мой код:

Timer.m :

 - (id) init {
    self = [super init];
    if(self) {
        _ticks = 0;
    }
    return self;
}

- (void) startWithTicks: (unsigned int) ticks {
    _ticks = ticks; //_ticks is an unsigned int instance variable
    if(_ticks > 0) {
        [NSTimer scheduledTimerWithTimeInterval: 1.0
                         target: self
                    selector: @selector(onTick:)
                    userInfo: nil
                     repeats: YES];
    }
}

- (void) onTick: (NSTimer*) timer {
    NSLog(@"tick");
    _ticks--;
    if(_ticks == 0) {
        [timer invalidate];
        timer = nil;
    }
}
  

main.m :

 int main(int argc, const char* argv[]) {
    Timer* t = [[Timer alloc] init];
    NSLog(@"Setting timer");
    [t startWithTicks: 3];
    usleep(5000);
    NSLog(@"End of timer");
    return 0;
}
  

Я бы ожидал, что результат будет

 Setting timer
tick
tick
tick
End of timer
  

Однако результат является

 Setting timer
End of timer
  

Почему это и как я могу это исправить?

Комментарии:

1. Вы уверены, что экземпляр таймера создан? Установите точку останова после ‘if(_ticks > 0) {‘

2. Возможно, usleep () вмешивается в работу таймера.. попробуйте удалить его

3. @PaulvanRoosendaal Я уверен, что if(_ticks > 0) выполняется. Кроме того, usleep() это просто способ показать, что код, следующий за таймером, не завершается до освобождения таймера.

Ответ №1:

Таймер не будет запускаться, пока ваш поток находится в спящем режиме.

Ваш код класса timer работает нормально, если вы используете его из ViewController.

Если вместо этого вы хотели бы использовать его в основном методе, вы захотите явно запустить mainRunLoop. Попробуйте настроить свой основной метод на это:

 int main(int argc, char * argv[]) {
    Timer *timer = [[Timer alloc] init];
    NSLog(@"Setting Timer");
    [timer startWithTicks:3];
    [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:3]];
    NSLog(@"End of Timer");
    return 0;
}
  

для запуска mainRunLoop, работающего в течение 3 секунд, который должен выдавать желаемый результат.

https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html
https://developer.apple.com/documentation/foundation/nsrunloop