NSOperationQueue waitUntilAllOperationsAreFinished does not work in the background

The application I'm working on periodically updates its local data cache from the application server (10+ requests, each of which takes a sufficient amount of time). I am currently executing these requests asynchronously so as not to block the UI thread. Since these queries take some time and then are loaded into the main data, I would like to use the beginBackgroundTaskWithExpirationHandlerdependent behavior of the operation NSOperationQueue.

After I added all my requests to the operation queue, I use it waitUntilAllOperationsAreFinishedto lock until all operations are completed (this is not in the main thread). The problem that I see in my prototype is that when I launch the application and immediately its background (press the home button) waitUntilAllOperationsAreFinishedremains locked even after all operations are completed ... but as soon as I open the application again, the handler ends. If I run the application and leave it in the foreground, everything will end perfectly. This behavior does not always occur when in my actual application, but with the code example below it looks like:

#import "ViewController.h"

@interface ViewController ()

@property (assign, nonatomic) UIBackgroundTaskIdentifier task;
@property (strong, nonatomic) NSOperationQueue *queue;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    [self performSelectorInBackground:@selector(queueItUp) withObject:nil];
}

- (void)queueItUp {
    UIApplication *application = [UIApplication sharedApplication];

    self.queue = [[NSOperationQueue alloc] init];
    self.task = [application beginBackgroundTaskWithExpirationHandler:^{
        NSLog(@"Took too long!");

        [self.queue cancelAllOperations];
        [application endBackgroundTask:self.task];
        self.task = UIBackgroundTaskInvalid;
    }];

    for (int i = 0; i < 5; i++) {
        [self.queue addOperationWithBlock:^{
            [NSThread sleepForTimeInterval:3];
            NSLog(@"Finished operation.");
        }];
    }


    NSLog(@"Waiting until all operations are finished.");

    [self.queue waitUntilAllOperationsAreFinished];

    [application endBackgroundTask:self.task];
    self.task = UIBackgroundTaskInvalid;

    NSLog(@"All done :)");
}

@end

What am I doing wrong?

thank

+5
source share
2 answers

iOS 6.1 iPhone . [application endBackgroundTask:self.task];, .

, , , , . , - . , .

NSLog(@"All done"); endBackgroundTask:, .

+4

, . NSLog(@"All done :)");, . , runloop, , . , . , , . :

    [[self queue] addOperationWithBlock:^{
        NSLog(@"All done :)");
    }];

. , , .

, waitUntilAllOperationsAreFinished. , .

, -, . NSOperation , . , , . Concurrency

+1

All Articles