-1

I have a UILabel that I would like to update as a countdown timer. Currently I am using an NSTimer to execute a method when the allotted inactivity time has passed. I found the code for setting up the desired NSTimer from this SO thread. I'm using the example code posted by Chris Miles in one of the view controllers for the application, and the method is executing properly when the idle time reaches the kMaxIdleTimeSeconds.

However I was hoping to take the code example posted by Chris Miles a step further by updating a UILabel in the view controller with the remaining idle time. Should I use a completely separate NSTimer to do this, or is there a way to update UILabel with idle time remaining with the current NSTimer before logout?

The view controller implementation file for the application looks like the following,

#import "ViewControllerCreate.h"
#import "math.h"

@interface ViewControllerHome ()

#define kMaxIdleTimeSeconds 20.0

@implementation ViewControllerHome

@end

- (void)viewDidLoad
{

// 5AUG13 - idle time logout
    [self resetIdleTimer];

    int idleTimerTime_int;

    idleTimerTime_int = (int)roundf(kMaxIdleTimeSeconds);

    _idleTimerTime.text = [NSString stringWithFormat:@"%d secs til",idleTimerTime_int];

}

- (void)viewDidUnload
{
[self setIdleTimerTime:nil];
    // set the idleTimer to nil so the idleTimer doesn't tick away on the welcome screen.
    idleTimer = nil;
    [super viewDidUnload];
}

#pragma mark -
#pragma mark Handling idle timeout

- (void)resetIdleTimer {
    if (!idleTimer ) {
        idleTimer = [NSTimer scheduledTimerWithTimeInterval:kMaxIdleTimeSeconds
                                                      target:self
                                                    selector:@selector(idleTimerExceeded)
                                                    userInfo:nil
                                                    repeats:YES];
    }
    else {
        if(fabs([idleTimer.fireDate timeIntervalSinceNow]) < kMaxIdleTimeSeconds-1.0) {
            [idleTimer setFireDate:[NSDate dateWithTimeIntervalSinceNow:kMaxIdleTimeSeconds]];
        }
    }
}

- (void)idleTimerExceeded {
    NSLog(@"lets see what happens");
    [idleTimer invalidate];
    [self logout:nil];
    [self resetIdleTimer];
}

// method is fired when user touches screen.
- (UIResponder *)nextResponder {
    [self resetIdleTimer];
    return [super nextResponder];
}

@end
Community
  • 1
  • 1
ipatch
  • 3,933
  • 8
  • 60
  • 99

1 Answers1

1

I wouldn't use the code you posted at all. Why not start the label with the max idle time, then call the timer's action method once every second, and subtract 1 from the label's text's intValue. When the label's value reaches 0, do what ever you need to do, and invalidate the timer.

Something like this:

- (void)viewDidLoad {
      [super viewDidLoad];
      self.label.text = @"1000";
      [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(countDown:) userInfo:nil repeats:YES];
}

-(void)countDown:(NSTimer *) aTimer {
      self.label.text = [NSString stringWithFormat:@"%d",[self.label.text  intValue] - 1];
      if ([self.label.text isEqualToString:@"0"]) {
           //do whatever
           [aTimer invalidate];
      }
}
rdelmar
  • 103,982
  • 12
  • 207
  • 218
  • would you care to elaborate on your answer with a code example? – ipatch Aug 06 '13 at 19:21
  • @Chris, I've updated with a code example. – rdelmar Aug 06 '13 at 19:27
  • @rdelmar thank you very much, the code example was very helpful. – ipatch Aug 06 '13 at 19:47
  • You really shouldn't use a direct countdown `[self.label.text intValue] - 1` like this if you care about accuracy. The `NSTimer` will not fire at exact one second intervals, and delays will accumulate. – jscs Aug 06 '13 at 20:09