Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When call completionHandler with Background Fetch in iOS 7 with NSOperation

i want integrate the Background Fetch in my iOS app, i have enabled the Background Fetch in the capabilities of the project, then i have insert this:

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [application setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];

to enable the background fetch with minimum interval, then in App delegate i insert the delegate method:

-(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
    NSLog(@"Call fetch iCloud");
    [[MySingleton sharedManager] startCheckOnCloud];
}

My question is this, i know that i have to call this:

completionHandler(UIBackgroundFetchResultNewData);

somewhere, i have see a lot of example that insert that completionHandler in the performFetchWithCompletionHandler delegate method, but in that method i call a NSOperation in a Singleton, that operation check che iCloud folder and make some changes in a Sqlite DB, if i do this:

    -(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
    {
        NSLog(@"Call fetch iCloud");
        [[MySingleton sharedManager] startCheckOnCloud];
        completionHandler(UIBackgroundFetchResultNewData);
    }

the operation start and do anything, maybe because the system make it sleep instantly, instead if i remove the completionHandler give me this warning:

Warning: Application delegate received call to -application:performFetchWithCompletionHandler: but the completion handler was never called.

so my question is, how i can handle the completionHandler with NSOperation?

like image 877
Piero Avatar asked Nov 23 '13 16:11

Piero


1 Answers

You must call the completion handler with 30 seconds, but you don't have to block the main thread while you perform the query.

It appears that internally UIKit is detecting that you have not stored a strong reference to the completionHandler and then logging that warning. If you perform something simple like this:

- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void  (^)(UIBackgroundFetchResult))completionHandler
{
    // Start asynchronous NSOperation, or some other check

    // Ideally the NSOperation would notify when it has completed, but just for
    // illustrative purposes, call the completion block after 20 seconds.
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 20 * NSEC_PER_SEC), 
                   dispatch_get_main_queue(), ^{
        // Check result of your operation and call completion block with the result
        completionHandler(UIBackgroundFetchResultNewData);
    });
}

You will notice that the warning isn't logged even, though the method exited before calling the completion block.

like image 171
Alex MDC Avatar answered Nov 15 '22 13:11

Alex MDC