Search code examples
iospush-notificationnstimer

Pass completionHandler to NSTimer


In iOS 7 they added the function -(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler which allows you to do something in the background when you get a push notification. However they only give you about 30 seconds to do something.

I want to make an NSTimer to let me know if my 30 seconds are almost up, and have it finish what it was doing. It would be nice to pass the completion handler through the timer, so that I can call it when I'm done.

Is there a way to pass the completion handler, (void (^)(UIBackgroundFetchResult))completionHandler with the NSTimer and call it from the called function?


Solution

  • Yeah, hold the completion handler block in an instance variable:

    typedef void(^BackgroundCompletionHandler)(UIBackgroundFetchResult);
    
    @interface YourClass ()
    {
        BackgroundCompletionHandler _backgroundCompletionHandler;
    }
    

    And use a common method to call this stored block:

    -(void)          application:(UIApplication *)application
    didReceiveRemoteNotification:(NSDictionary *)userInfo
          fetchCompletionHandler:(BackgroundCompletionHandler)completionHandler
    {
        _backgroundCompletionHandler = completionHandler;
    
        [NSTimer scheduledTimerWithTimeInterval:30.0
                                         target:self
                                       selector:@selector(timeUp:)
                                       userInfo:nil
                                        repeats:NO];
    
        // Do work
    
        [self callBackgroundCompletionHandler:YES];
    }
    
    - (void)timeUp:(NSTimer *)timer
    {
        [self callBackgroundCompletionHandler:NO];
    }
    
    - (void)callBackgroundCompletionHandler:(BOOL)succeeded
    {
        @synchronized(self)
        {
            if (_backgrondCompletionHandler) {
                _backgroundCompletionHandler(succeeded ? UIBackgroundFetchResultNewData : UIBackgroundFetchResultFailed);
                _backgroundCompletionHandler = NULL;
            }
        }
    }