Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ios: Queue blocks in background and execute when network becomes available

I am developing an app using parse.com API (hosted backend which provides API to save data on their servers). I want to be able to use the app seamlessly online and offline. For this I would need to use a queue where I can place blocks that require network access. When network does become available, the blocks should be executed serially and when the network goes offline, then the queue processing should be suspended.

I was thinking of using GCD with suspend/resume as the network becomes available/unavailable. I was wondering if there are any better options? Will this work if the app is put in the background? Case in point here is that a user saves some data when the network is unavailable (which gets queued) and then puts the app in the background. Now when the network becomes available, is it possible to do the saving in the background automagically?

like image 924
Devang Avatar asked May 24 '12 08:05

Devang


2 Answers

I do exactly what you're aiming for using an NSOperationQueue. First, create a serial queue and suspend it by default:

self.operationQueue = [[[NSOperationQueue alloc] init] autorelease];
self.operationQueue.maxConcurrentOperationCount = 1;
[self.operationQueue setSuspended:YES];

Then, create a Reachability instance and register for the kReachabilityChangedNotification:

[[NSNotificationCenter defaultCenter] addObserver:manager
                                         selector:@selector(handleNetworkChange:) 
                                             name:kReachabilityChangedNotification 
                                           object:nil];

[self setReachability:[Reachability reachabilityWithHostName:@"your.host.com"]];
[self.reachability startNotifier];

Now, start and stop your queue when the network status changes:

-(void)handleNetworkChange:(NSNotification *)sender {
    NetworkStatus remoteHostStatus = [self.reachability currentReachabilityStatus];

    if (remoteHostStatus == NotReachable) {
        [self.operationQueue setSuspended:YES];
    }
    else {
        [self.operationQueue setSuspended:NO];
    }
}

You can queue your blocks with:

[self.operationQueue addOperationWithBlock:^{
    // do something requiring network access
}]; 

Suspending a queue will only prevent operations from starting--it won't suspend an operation in progress. There's always a chance that you could lose network while an operation is executing, so you should account for that in your operation.

like image 194
Christopher Pickslay Avatar answered Oct 21 '22 15:10

Christopher Pickslay


Check out -[PFObject saveEventually]. This should do what you're trying to do automatically and has the additional benefit of being resilient against app termination.

like image 33
Thomas Bouldin Avatar answered Oct 21 '22 15:10

Thomas Bouldin