objective-cgnustep

Calling a method every second doesn't work


I am trying to schedule a GNUStep Objective-C method call to run every second for a variable number of seconds. I am trying to use NSTimer to schedule the method call, but the handler method never gets called.

Here is my code:

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;
}

I would expect the output to be

Setting timer
tick
tick
tick
End of timer

However, the output is

Setting timer
End of timer

Why is this and how can I fix it?


Solution

  • The timer won't run while your thread is sleeping.

    Your timer class code works fine if you're using it from a ViewController.

    If instead you'd like to use it within the main method, you'll want to explicitly run the mainRunLoop. Try adjusting your main method to this:

    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;
    }
    

    to run the mainRunLoop running for 3 seconds, which should produce your desired output.

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