Search code examples
iosobjective-cnstimerviewdidloaduiapplicationdelegate

ios updateDisplay on a timer


I've got a somewhat complicated iOS user interface, where I need to reload a particular cell of a UICollectionView every second to show time (kind of like a complicated stopwatch), I also need to do a few other things every second in this call.

Part 1 of question


My question is what is the best practice for doing this type of problem?

Option 1 (use recursive call)

- (void)viewDidLoad
{
   [self runUpdateDisplayLoop];
}
- (void)runUpdateDisplayLoop
{
   //do stuff (reload cell, etc)
       
   //Recurissively Call Every Second
    dispatch_async(dispatch_get_main_queue(), ^{
        
        [self performSelector:@selector(runUpdateDisplayLoop) withObject:nil afterDelay:1.0];
        
    });
}

Option 2 (use NSTimer)

- (void)viewDidLoad
{
   NSTimer *updateDisplayTimer = [NSTimer scheduledTimerWithTimeInterval:1.0
                                              target:self 
                                            selector:@selector(runUpdateDisplayLoop:) 
                                            userInfo:nil 
                                             repeats:YES];
}

- (void)updateDisplayLoop:(NSTimer *) theTimer
{
 //do stuff (reload cell, etc)
}

Part 2 of Question


In either case, what is the best place to initiate and terminate these loops?

If I put them in ViewDidLoad they will continue being called even when I've navigated away from the relevant view, i'd rather only have the loop running when it needs to be. On the other hand, the loop must be running every time the view is displayed (even when the view has been dismissed in all variety of ways - app dismissed and reopened, phone call interruption, etc). In regards to app lifecycle, i'm targeting iOS 5 and iOS 6.

I'm guessing there is a solution involving "viewWillAppear" and "viewWillDisappear", but i'm leery of getting into situations where one or the other isn't called. I also don't want to spawn multiple loops by making any false assumptions.


Solution

  • For Part 1

    I recommend using a timer. The main reason is so you can stop the process by invalidating the timer. Using performSelector you can achieve something similar but I wouldn't go that route. To each their own.

    For Part 2

    You do want to use viewWillAppear (or viewDidAppear) and viewDidDisappear (or viewWillDisappear). Setup the timer on appear and tear it down on disappear.

    Check out RespondingtoDisplay-Notifications

    Hope that sheds a light on things and addresses your "but i'm leery of getting into situations where one or the other isn't called." concern