Apple Programming Guide for iOS iOS Background Guide Example?

So, on this page there is an example of background execution: https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html#//apple_ref/doc/uid/TP40007072-CH4- SW1 , here is an example:

- (void)applicationDidEnterBackground:(UIApplication *)application {

    bgTask = [application beginBackgroundTaskWithName:@"MyTask" expirationHandler:^{

        // Clean up any unfinished task business by marking where you
        // stopped or ending the task outright.
        [application endBackgroundTask:bgTask];

        bgTask = UIBackgroundTaskInvalid;
    }];

    // Start the long-running task and return immediately.
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        // Do the work associated with the task, preferably in chunks.

        [application endBackgroundTask:bgTask];
        bgTask = UIBackgroundTaskInvalid;
    });

}

They say that it bgTaskis defined in the class as a variable. Thus, for each instance of a class (object), there is one property bgTask. If applicationDidEnterBackgroundyou had to call several times before the asynchronous block ends, is there no danger of the race condition here? I mean, what bgTaskwill change its value, but endBackgroundTaskwill be called with a new task value instead of the old value?

:

__block UIBackgroundTaskIdentifier bgTask;

beginBackgroundTaskWithName?

+4
3

bgTask, AppDelegate, - VC . , bgTask .

. , , bgTask. , . , ( ). , bgTask ( ), endBackgroundTask:. bgTask UIBackgroundTaskInvalid, , endBackgroundTask:. , , , , expiration - .

, . ( AppDelegate applicationDidEnterBackground:):

__block UIBackgroundTaskIdentifier bgTask = [application beginBackgroundTaskWithName:@"MyTask" expirationHandler:^{
    // Clean up any unfinished task business by marking where you
    // stopped or ending the task outright.
    NSLog(@"Expired");
    [application endBackgroundTask:bgTask];
    bgTask = UIBackgroundTaskInvalid;
}];

NSLog(@"Backgrounded: %@", @(bgTask));

// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    // Do the work associated with the task, preferably in chunks.
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"Done! %@", @(bgTask));
        [application endBackgroundTask:bgTask];
        bgTask = UIBackgroundTaskInvalid;
    });
});

, bgTask 10 ( dispatch_after).

+2

, , , :
Background, iOS - applicationDidEnterBackground:.
, .
, applicationDidEnterBackground: , bgTask , . . , bgTask .
, , . , , .
, , . , .

+1

You are right, when called a second time, it applicationDidEnterBackgroundwill cause problems. But in order for this method to be called a second time, the application must first be brought back to the forefront. Thus, the solution is easy. Just call your expiration handler from applicationWillEnterForeground:

- (void)expireBackgroundTask {
    // Clean up any unfinished task business by marking where you
    // stopped or ending the task outright.
    [application endBackgroundTask:bgTask];            
    bgTask = UIBackgroundTaskInvalid;
}

- (void)applicationDidEnterBackground:(UIApplication *)application {

    bgTask = [application beginBackgroundTaskWithName:@"MyTask" expirationHandler:^{
        [self expireBackgroundTask];
    }];

    // Start the long-running task and return immediately.
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        // Do the work associated with the task, preferably in chunks.

        [application endBackgroundTask:bgTask];
        bgTask = UIBackgroundTaskInvalid;
    });

}

- (void)applicationWillEnterForeground:(UIApplication *)application
{
    [self expireBackgroundTask];
}
+1
source

Source: https://habr.com/ru/post/1625540/


All Articles