简体   繁体   中英

NSTimer doesn't call method

I'm really frustrated now, googled the whole internet, stumbled through SO and still didn't find a solution.

I'm trying to implement an NSTimer, but the method which I defined doesn't get called. (seconds are set correctly, checked it with breakpoints). Here is the code:

- (void) setTimerForAlarm:(Alarm *)alarm {
    NSTimeInterval seconds = [[alarm alarmDate] timeIntervalSinceNow];
    theTimer = [NSTimer timerWithTimeInterval:seconds 
                            target:self 
                          selector:@selector(showAlarm:)
                          userInfo:alarm repeats:NO];
}

- (void) showAlarm:(Alarm *)alarm {
    NSLog(@"Alarm: %@", [alarm alarmText]);
}

The object "theTimer" is deined with @property:

@interface FooAppDelegate : NSObject <NSApplicationDelegate, NSWindowDelegate>  {
@private

    NSTimer *theTimer;

}

@property (nonatomic, retain) NSTimer *theTimer;

- (void) setTimerForAlarm:(Alarm *)alarm;
- (void) showAlarm:(Alarm *)alarm;

What am I doing wrong?

timerWithTimeInterval simply creates a timer, but doesn't add it to any run loops for execution. Try

self.theTimer = [NSTimer scheduledTimerWithTimeInterval:seconds 
                        target:self 
                      selector:@selector(showAlarm:)
                      userInfo:alarm repeats:NO];

instead.

Also don't forget to check if

+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)seconds 
                                     target:(id)target 
                                   selector:(SEL)aSelector 
                                   userInfo:(id)userInfo 
                                    repeats:(BOOL)repeats 

is called in the main thread.

You've created an NSTimer object but you haven't scheduled it to be run. timerWithTimeInterval:target:selector:userInfo:repeats: creates a timer that you can schedule to run later, for example, to create a timer at application launch and have it start counting when the user presses a button. Either call

[[NSRunLoop currentRunLoop] addTimer:theTimer forMode:NSDefaultRunLoopMode]

at the end of setTimerForAlarm or replace

theTimer = [NSTimer timerWithTimeInterval:seconds 
                            target:self 
                          selector:@selector(showAlarm:)
                          userInfo:alarm repeats:NO];

with

theTimer = [NSTimer scheduledTimerWithTimeInterval:seconds 
                            target:self 
                          selector:@selector(showAlarm:)
                          userInfo:alarm repeats:NO];

which creates a timer and immediately schedules it.

Well you may want to actually schedule your NSTimer on the run loop :) instead of timerWithTimeInterval use scheduledTimerWithTimeInterval .

theTimer = [NSTimer scheduledTimerWithTimeInterval:seconds 
                        target:self 
                      selector:@selector(showAlarm:)
                      userInfo:alarm repeats:NO];

While all of the answers are right, there is an even simpler solution that doesn't involve a NSTimer at all. Your setTimerForAlarm: implementation can be reduced to one simple line:

[self performSelector:@selector(showAlarm:) withObject:alarm afterDelay:[[alarm alarmDate] timeIntervalSinceNow]]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM