mirror of
https://github.com/zhigang1992/RestKit.git
synced 2026-01-12 22:51:50 +08:00
Introduce a new heuristic based approach for determining if a response can skip the mapping process. Also introduces a new Network + CoreData logging component and reduces the chattiness of the debug logging level for Core Data Network events.
This commit is contained in:
@@ -35,13 +35,12 @@
|
||||
|
||||
// Set Logging Component
|
||||
#undef RKLogComponent
|
||||
#define RKLogComponent RKlcl_cRestKitCoreData
|
||||
#define RKLogComponent RKlcl_cRestKitNetworkCoreData
|
||||
|
||||
@interface RKEntityMappingEvent : NSObject
|
||||
@property (nonatomic, copy) id rootKey;
|
||||
@property (nonatomic, copy) NSString *keyPath;
|
||||
@property (nonatomic, strong) RKEntityMapping *entityMapping;
|
||||
@property (nonatomic, readonly) BOOL canSkipMapping;
|
||||
|
||||
+ (instancetype)eventWithRootKey:(id)rootKey keyPath:(NSString *)keyPath entityMapping:(RKEntityMapping *)entityMapping;
|
||||
@end
|
||||
@@ -299,6 +298,8 @@ static NSURL *RKRelativeURLFromURLAndResponseDescriptors(NSURL *URL, NSArray *re
|
||||
@property (nonatomic, strong, readwrite) RKMappingResult *mappingResult;
|
||||
@property (nonatomic, copy) id (^willMapDeserializedResponseBlock)(id deserializedResponseBody);
|
||||
@property (nonatomic, strong) NSArray *entityMappingEvents;
|
||||
|
||||
@property (nonatomic, strong) NSCachedURLResponse *cachedResponse;
|
||||
@end
|
||||
|
||||
@implementation RKManagedObjectRequestOperation
|
||||
@@ -312,6 +313,7 @@ static NSURL *RKRelativeURLFromURLAndResponseDescriptors(NSURL *URL, NSArray *re
|
||||
if (self) {
|
||||
self.savesToPersistentStore = YES;
|
||||
self.deletesOrphanedObjects = YES;
|
||||
self.cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:requestOperation.request];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -372,14 +374,31 @@ static NSURL *RKRelativeURLFromURLAndResponseDescriptors(NSURL *URL, NSArray *re
|
||||
// RKResponseHasBeenMappedCacheUserInfoKey is stored by RKObjectRequestOperation
|
||||
- (BOOL)canSkipMapping
|
||||
{
|
||||
NSCachedURLResponse *cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:self.HTTPRequestOperation.request];
|
||||
// Is the request cacheable
|
||||
if (!self.cachedResponse) return NO;
|
||||
NSURLRequest *request = self.HTTPRequestOperation.request;
|
||||
if (! [[request HTTPMethod] isEqualToString:@"GET"] && ! [[request HTTPMethod] isEqualToString:@"HEAD"]) return NO;
|
||||
NSHTTPURLResponse *response = (NSHTTPURLResponse *)self.HTTPRequestOperation.response;
|
||||
if (! [RKCacheableStatusCodes() containsIndex:response.statusCode]) return NO;
|
||||
|
||||
// Check for a change in the Etag
|
||||
NSString *cachedEtag = [[(NSHTTPURLResponse *)[self.cachedResponse response] allHeaderFields] objectForKey:@"Etag"];
|
||||
NSString *responseEtag = [[response allHeaderFields] objectForKey:@"Etag"];
|
||||
if (! [cachedEtag isEqualToString:responseEtag]) return NO;
|
||||
|
||||
// Response data has changed
|
||||
NSData *responseData = self.HTTPRequestOperation.responseData;
|
||||
if (! [responseData isEqualToData:[self.cachedResponse data]]) return NO;
|
||||
|
||||
// Check that we have mapped this response previously
|
||||
NSCachedURLResponse *cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:request];
|
||||
return [[cachedResponse.userInfo objectForKey:RKResponseHasBeenMappedCacheUserInfoKey] boolValue];
|
||||
}
|
||||
|
||||
- (RKMappingResult *)performMappingOnResponse:(NSError **)error
|
||||
{
|
||||
if (self.canSkipMapping) {
|
||||
RKLogDebug(@"Managed object mapping requested for cached response: skipping mapping...");
|
||||
if ([self canSkipMapping]) {
|
||||
RKLogDebug(@"Managed object mapping requested for cached response which was previously mapped: skipping...");
|
||||
NSURL *URL = RKRelativeURLFromURLAndResponseDescriptors(self.HTTPRequestOperation.response.URL, self.responseDescriptors);
|
||||
NSArray *fetchRequests = RKArrayOfFetchRequestFromBlocksWithURL(self.fetchRequestBlocks, URL);
|
||||
NSMutableArray *managedObjects = [NSMutableArray array];
|
||||
@@ -470,7 +489,7 @@ static NSURL *RKRelativeURLFromURLAndResponseDescriptors(NSURL *URL, NSArray *re
|
||||
RKLogTrace(@"Fetched local objects matching URL '%@' with fetch request '%@': %@", URL, fetchRequest, _blockObjects);
|
||||
[localObjects addObjectsFromArray:_blockObjects];
|
||||
} else {
|
||||
RKLogDebug(@"Fetch request block %@ returned nil fetch request for URL: '%@'", fetchRequestBlock, URL);
|
||||
RKLogTrace(@"Fetch request block %@ returned nil fetch request for URL: '%@'", fetchRequestBlock, URL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -489,7 +508,7 @@ static NSURL *RKRelativeURLFromURLAndResponseDescriptors(NSURL *URL, NSArray *re
|
||||
return YES;
|
||||
}
|
||||
|
||||
if (self.canSkipMapping) {
|
||||
if ([self canSkipMapping]) {
|
||||
RKLogDebug(@"Skipping deletion of orphaned objects: 304 (Not Modified) status code encountered");
|
||||
return YES;
|
||||
}
|
||||
|
||||
@@ -78,6 +78,13 @@ NSRange RKStatusCodeRangeForClass(RKStatusCodeClass statusCodeClass);
|
||||
*/
|
||||
NSIndexSet *RKStatusCodeIndexSetForClass(RKStatusCodeClass statusCodeClass);
|
||||
|
||||
/**
|
||||
Creates and returns a new index set including all HTTP response status codes that are cacheable.
|
||||
|
||||
@return A new index set containing all cacheable status codes.
|
||||
*/
|
||||
NSIndexSet *RKCacheableStatusCodes();
|
||||
|
||||
/**
|
||||
Returns string representation of a given HTTP status code.
|
||||
|
||||
|
||||
@@ -32,6 +32,20 @@ NSIndexSet *RKStatusCodeIndexSetForClass(RKStatusCodeClass statusCodeClass)
|
||||
return [NSIndexSet indexSetWithIndexesInRange:RKStatusCodeRangeForClass(statusCodeClass)];
|
||||
}
|
||||
|
||||
NSIndexSet *RKCacheableStatusCodes()
|
||||
{
|
||||
NSMutableIndexSet *cacheableStatusCodes = [NSMutableIndexSet indexSet];
|
||||
[cacheableStatusCodes addIndex:200];
|
||||
[cacheableStatusCodes addIndex:304];
|
||||
[cacheableStatusCodes addIndex:203];
|
||||
[cacheableStatusCodes addIndex:300];
|
||||
[cacheableStatusCodes addIndex:301];
|
||||
[cacheableStatusCodes addIndex:302];
|
||||
[cacheableStatusCodes addIndex:307];
|
||||
[cacheableStatusCodes addIndex:410];
|
||||
return cacheableStatusCodes;
|
||||
}
|
||||
|
||||
NSString *RKStringFromRequestMethod(RKRequestMethod method)
|
||||
{
|
||||
switch (method) {
|
||||
|
||||
@@ -54,6 +54,7 @@ _RKlcl_component(RestKit, "restkit",
|
||||
_RKlcl_component(RestKitCoreData, "restkit.core_data", "RestKit/CoreData")
|
||||
_RKlcl_component(RestKitCoreDataCache, "restkit.core_data.cache", "RestKit/CoreData/Cache")
|
||||
_RKlcl_component(RestKitNetwork, "restkit.network", "RestKit/Network")
|
||||
_RKlcl_component(RestKitNetworkCoreData, "restkit.network.core_data", "RestKit/Network/CoreData")
|
||||
_RKlcl_component(RestKitObjectMapping, "restkit.object_mapping", "RestKit/ObjectMapping")
|
||||
_RKlcl_component(RestKitSearch, "restkit.search", "RestKit/Search")
|
||||
_RKlcl_component(RestKitSupport, "restkit.support", "RestKit/Support")
|
||||
|
||||
Reference in New Issue
Block a user