[#11477593] Implemented background request policies and Specs. This provides functionality for continuing a request in the background using an iOS background task.

Introduces four modes for handling background requests:
* RKRequestBackgroundPolicyNone - The default behavior replicating pre-background behavior. No special action is taken with regards to backgrounding.
* RKRequestBackgroundPolicyCancel - On transition to the background, requests with this policy set will be cancelled automatically and the delegate informed.
* RKRequestBackgroundPolicyContinue - Requests with this policy will be continued in the background after the app has been transitioned.
* RKRequestBackgroundPolicyRequeue - Requests with this policy will be cancelled and then immediately placed onto the queue for processing the next time the app is returned to the foreground.
This commit is contained in:
Blake Watters
2011-03-29 13:23:17 -04:00
parent 334db23e9d
commit a648d26460
16 changed files with 364 additions and 93 deletions

View File

@@ -6,6 +6,7 @@
// Copyright 2010 Two Toasters. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "RKRequestQueue.h"
#import "RKResponse.h"
#import "RKNotifications.h"
@@ -39,6 +40,7 @@ static const NSInteger kMaxConcurrentLoads = 5;
_requests = [[NSMutableArray alloc] init];
_suspended = NO;
_totalLoading = 0;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(responseDidLoad:)
name:RKResponseReceivedNotification
@@ -47,14 +49,25 @@ static const NSInteger kMaxConcurrentLoads = 5;
selector:@selector(responseDidLoad:)
name:RKRequestFailedWithErrorNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(willTransitionToBackground)
name:UIApplicationDidEnterBackgroundNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(willTransitionToForeground)
name:UIApplicationWillEnterForegroundNotification
object:nil];
}
return self;
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[_queueTimer invalidate];
[_requests release];
_requests = nil;
[super dealloc];
}
@@ -68,14 +81,10 @@ static const NSInteger kMaxConcurrentLoads = 5;
}
}
- (void)dispatchRequest:(RKRequest*)request {
[request performSelector:@selector(fireAsynchronousRequest)];
}
- (void)loadNextInQueue {
// This makes sure that the Request Queue does not fire off any requests until the Reachability state has been determined.
// This prevents the request queue from
if ([[[RKClient sharedClient] baseURLReachabilityObserver] networkStatus] == RKReachabilityIndeterminate) {
if ([[[RKClient sharedClient] baseURLReachabilityObserver] networkStatus] == RKReachabilityIndeterminate ||
self.suspended) {
_queueTimer = nil;
[self loadNextInQueueDelayed];
return;
@@ -89,7 +98,7 @@ static const NSInteger kMaxConcurrentLoads = 5;
for (RKRequest* request in requestsCopy) {
if (![request isLoading] && ![request isLoaded] && _totalLoading < kMaxConcurrentLoads) {
++_totalLoading;
[self dispatchRequest:request];
[request sendAsynchronously];
}
}
@@ -153,6 +162,10 @@ static const NSInteger kMaxConcurrentLoads = 5;
[pool drain];
}
- (BOOL)containsRequest:(RKRequest*)request {
return [_requests containsObject:request];
}
/**
* Invoked via observation when a request has loaded a response. Remove
* the completed request from the queue and continue processing
@@ -176,4 +189,15 @@ static const NSInteger kMaxConcurrentLoads = 5;
}
}
#pragma mark - Background Request Support
- (void)willTransitionToBackground {
// Suspend the queue so background requests do not trigger additional requests on state changes
self.suspended = YES;
}
- (void)willTransitionToForeground {
self.suspended = NO;
}
@end