Search code examples
iosobjective-cperformselector

Are performSelector afterDelay calls reset when applicationDidEnterBackground?


I totally understand if they are, but what I'm looking for is a timer that pauses when the application enters the background and unpauses after the user returns to the app. I do not need a background task; I just want to make sure that after approximately x minutes within the app a certain action occurs whether that is today or tomorrow.

Thanks! Brett


Solution

  • Backgrounding the app (assuming you have no background task) doesn't "pause" the timer. It's still counting down in theory so if the app is reopened, it will fire if enough time has passed. This goes for NSTimer's as well. (Let me know if you want more details as to why and I'll edit the answer).

    Consider using the following code:

    @implementation MyCustomClass {
        int elapsedTime;
        NSTimer *timer;
    }
    
    - (id) init {
        if ( ( self = [super init] ) ) {
            [[NSNotificationCenter defaultCenter] addObserver:self
                                                     selector:@selector(applicationEnteredBackground)
                                                         name:UIApplicationDidEnterBackgroundNotification
                                                       object:nil];
            [[NSNotificationCenter defaultCenter] addObserver:self
                                                     selector:@selector(applicationEnteredForeground)
                                                         name:UIApplicationDidBecomeActiveNotification
                                                       object:nil];
        }
        return self;
    }
    
    
    - (void) applicationEnteredForeground { 
        timer = [NSTimer timerWithTimeInterval:1
                                        target:self
                                      selector:@selector(timerTicked)
                                      userInfo:nil
                                       repeats:YES];
        [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
    }
    
    - (void) applicationEnteredBackground {
        [timer invalidate];
    }
    
    - (void) timerTicked {
        elapsedTime += 1;
        // If enough time passed, do something
    }