Question

I mean 12:01:00, 12:02:00 ...

In iOS7, I want to call a method when minute of time is changed. In other words, if now is 01:55:47, then I want to call a method at 01:56:00 -> 01:57:00 -> 01:58:00 ...

All I found about call a method is just about TimeInterval, but not I want.

I've tried this code:

NSTimeInterval roundedInterval = round([[NSDate date] timeIntervalSinceReferenceDate] / 60.0) * 60.0;
NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:roundedInterval];

NSTimer *timer = [[NSTimer alloc] initWithFireDate:date
                                          interval:60.0
                                            target:self
                                          selector:@selector(handleEveryMinutes:)
                                          userInfo:nil
                                           repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];

- (void)handleEveryMinutes:(NSTimer *)timer {
NSLog(@"one minute!");
}

But this method is not called at second 0.

Hope cool people can help me!

----- My answer -------

I also figure out why my code is not working correctly, I need add extra 60 seconds to the roundedInterval, which is the exact time of the next minute. If do not add 60 second, the fireDate is passed, so when I run my app, it have to fire immediately.

NSTimeInterval roundedInterval = round([[NSDate date] timeIntervalSinceReferenceDate] / 60.0) * 60.0 + 60; // the extra 60 is used to set the correct time Interval between next minute and referenced date.
NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:roundedInterval];

Now, it's working!

Was it helpful?

Solution

The key is to start that recurring timer at the right time. Get the current time and find out how many seconds we are into the current minute...

NSDateComponents *components = [[NSCalendar currentCalendar] components: NSSecondCalendarUnit fromDate:[NSDate date]];
NSInteger second = [components second];

From this we can get the number of seconds until the next minute...

NSInteger tillNextMinute = (60 - second) % 60;

I haven't tested that, but the idea of the mod 60 is to handle the case when second is zero. Now we're almost done...

[self performSelector:@selector(startTimer) withObject:nil afterDelay:tillNextMinute];

Then the code you began with...

- (void)startTimer {
    // contains the code you posted to start the timer
}

OTHER TIPS

The currently accepted answer will be incorrect by up to 1 second.

Here is how to get the next minute as precisely as possible:

// set clock to current date
NSDate *date = [NSDate date];
NSDateComponents *dateComponents = [[NSCalendar currentCalendar] components:NSSecondCalendarUnit fromDate:date];

NSTimeInterval timeSinceLastSecond = date.timeIntervalSince1970 - floor(date.timeIntervalSince1970);
NSTimeInterval timeToNextMinute = (60 - dateComponents.second) - timeSinceLastSecond;

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(timeToNextMinute * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

  [self handleEveryMinutes:nil];

});
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top