Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Display a timer for an iOS app that persists between view controllers

I've been trying to get a timer to show at the bottom left corner of my app by using an NSTimer, and making the "elapsed time" show as UILabel on the bottom left corner but it hasn't been working for me.

-(void)viewDidLoad
{
    NSTimer *aTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(aTime) userInfo:nil repeats:YES];
}

-(void)aTime
{
    NSLog(@"....Update Function Called....");

    static int i = 1;

    Label.text = [NSString stringWithFormat:@"%d",i];

    i++;
}

The timer actually works but I can't get it to be triggered by a button. I'm trying to get the timer to continue and not restart at 1 when it enters to the next storyboard/xib file.

like image 593
user1677210 Avatar asked Sep 21 '12 16:09

user1677210


2 Answers

For implementing the timer action on the button press, you need to write it on a IBAction method like:

- (IBAction) buttonPress
{
    NSTimer *aTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(aTime) userInfo:nil repeats:YES];
}

For storing the previous value, you can use NSUserDefaults or a SQLite database. For this purpose I'll suggest NSUserDefaults.

Change the aTime method like:

-(void)aTime
{
    NSUserDefaults *standardUserDefaults = [NSUserDefaults standardUserDefaults];
    id obj = [standardUserDefaults objectForKey:@"TimerValue"];
    int i = 0;

    if(obj != nil)
    {
        i = [obj intValue];
    }

    Label.text = [NSString stringWithFormat:@"%d",i];
    i++;

    [standardUserDefaults setObject:[NSNumber numberWithInt:i] forKey:@"TimerValue"];
    [standardUserDefaults synchronize];
}
like image 186
Midhun MP Avatar answered Nov 20 '22 04:11

Midhun MP


I think the problem is that the method aTime is in your view controller, when you enters another view, this view controller is released and you can't perform selector aTime anymore.

so I suggest that you put your aTime method and i to a singleton(or any object that won't be released when you enter another view) and set the singleton as the target of your timer.

also you should keep code below in your view controller so that you can update your label properly when you came back to this view.

-(void)viewDidLoad
{
    NSTimer *aTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(aTime) userInfo:nil repeats:YES];
}

-(void)aTime
{
    NSLog(@"....Update Function Called....");

    Label.text = [NSString stringWithFormat:@"%d",theSingleton.i];
}

better choice:

You can declare i as a property of your singleton, and then add an observer to i, then you'll get your label updated on time. call -startTimer when you want to count time.

the singleton:

  @interface Singleton

  @property (nonatomic,retain) NSNumber *i;

  @end

  @implementation

+(Singleton*)instance
{
    //the singleton code here
}

-(void)startTimer
{
    NSTimer *aTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(aTime) userInfo:nil repeats:YES];
}

-(void)aTime
{
    NSInteger temp = [i integerValue];
    temp ++;
    self.i = [NSNumber numberWithInteger:temp];
}

the view controller:

-(void)viewDidLoad
{
    [super viewDidLoad];
    [[Singleton instance] addObserver:self forKeyPath:@"i" options:NSKeyValueObservingOptionNew context:NULL]];
}


- (void)observeValueForKeyPath:(NSString *)keyPath
                  ofObject:(id)object
                    change:(NSDictionary *)change
                   context:(void *)context
{
    NSLog(@"....Update Function Called....");

    Label.text = [NSString stringWithFormat:@"%@",[Singleton instance].i];
}
like image 26
CarmeloS Avatar answered Nov 20 '22 05:11

CarmeloS