mirror of
https://github.com/zhigang1992/RestKit.git
synced 2026-04-18 12:13:25 +08:00
Merge branch 'master' of github.com:twotoasters/RestKit
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
#import "RKManagedObject.h"
|
||||
#import "RKURL.h"
|
||||
#import "RKNotifications.h"
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@implementation RKObjectLoader
|
||||
|
||||
@@ -29,7 +30,7 @@
|
||||
_mapper = [mapper retain];
|
||||
self.managedObjectStore = nil;
|
||||
_targetObjectID = nil;
|
||||
|
||||
|
||||
[[RKClient sharedClient] setupRequest:self];
|
||||
}
|
||||
return self;
|
||||
@@ -45,7 +46,7 @@
|
||||
[_targetObject release];
|
||||
_targetObject = nil;
|
||||
[_targetObjectID release];
|
||||
_targetObjectID = nil;
|
||||
_targetObjectID = nil;
|
||||
self.managedObjectStore = nil;
|
||||
[super dealloc];
|
||||
}
|
||||
@@ -54,10 +55,10 @@
|
||||
[_targetObject release];
|
||||
_targetObject = nil;
|
||||
_targetObject = [targetObject retain];
|
||||
|
||||
|
||||
[_targetObjectID release];
|
||||
_targetObjectID = nil;
|
||||
|
||||
|
||||
if ([targetObject isKindOfClass:[NSManagedObject class]]) {
|
||||
_targetObjectID = [[(NSManagedObject*)targetObject objectID] retain];
|
||||
}
|
||||
@@ -68,10 +69,10 @@
|
||||
|
||||
- (void)responseProcessingSuccessful:(BOOL)successful withError:(NSError*)error {
|
||||
_isLoading = NO;
|
||||
|
||||
|
||||
NSDate* receivedAt = [NSDate date];
|
||||
if (successful) {
|
||||
_isLoaded = YES;
|
||||
_isLoaded = YES;
|
||||
NSDictionary* userInfo = [NSDictionary dictionaryWithObjectsAndKeys:[self HTTPMethod], @"HTTPMethod",
|
||||
[self URL], @"URL",
|
||||
receivedAt, @"receivedAt",
|
||||
@@ -80,7 +81,7 @@
|
||||
object:_response
|
||||
userInfo:userInfo];
|
||||
} else {
|
||||
NSDictionary* userInfo = [NSDictionary dictionaryWithObjectsAndKeys:[self HTTPMethod], @"HTTPMethod",
|
||||
NSDictionary* userInfo = [NSDictionary dictionaryWithObjectsAndKeys:[self HTTPMethod], @"HTTPMethod",
|
||||
[self URL], @"URL",
|
||||
receivedAt, @"receivedAt",
|
||||
error, @"error",
|
||||
@@ -94,16 +95,30 @@
|
||||
- (BOOL)encounteredErrorWhileProcessingRequest:(RKResponse*)response {
|
||||
if ([response isFailure]) {
|
||||
[(NSObject<RKObjectLoaderDelegate>*)_delegate objectLoader:self didFailWithError:response.failureError];
|
||||
|
||||
|
||||
[self responseProcessingSuccessful:NO withError:response.failureError];
|
||||
|
||||
|
||||
return YES;
|
||||
} else if ([response isError]) {
|
||||
NSError* error = nil;
|
||||
|
||||
|
||||
if ([response isJSON]) {
|
||||
error = [_mapper parseErrorFromString:[response bodyAsString]];
|
||||
[(NSObject<RKObjectLoaderDelegate>*)_delegate objectLoader:self didFailWithError:error];
|
||||
|
||||
} else if ([response isServiceUnavailable] && [[RKClient sharedClient] serviceUnavailableAlertEnabled]) {
|
||||
if ([_delegate respondsToSelector:@selector(objectLoaderDidLoadUnexpectedResponse:)]) {
|
||||
[(NSObject<RKObjectLoaderDelegate>*)_delegate objectLoaderDidLoadUnexpectedResponse:self];
|
||||
}
|
||||
|
||||
UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:[[RKClient sharedClient] serviceUnavailableAlertTitle]
|
||||
message:[[RKClient sharedClient] serviceUnavailableAlertMessage]
|
||||
delegate:nil
|
||||
cancelButtonTitle:NSLocalizedString(@"OK", nil)
|
||||
otherButtonTitles:nil];
|
||||
[alertView show];
|
||||
[alertView release];
|
||||
|
||||
} else {
|
||||
// TODO: We've likely run into a maintenance page here. Consider adding the ability
|
||||
// to put the stack into offline mode in response...
|
||||
@@ -111,9 +126,9 @@
|
||||
[(NSObject<RKObjectLoaderDelegate>*)_delegate objectLoaderDidLoadUnexpectedResponse:self];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[self responseProcessingSuccessful:NO withError:error];
|
||||
|
||||
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
@@ -122,7 +137,7 @@
|
||||
- (void)informDelegateOfObjectLoadWithInfoDictionary:(NSDictionary*)dictionary {
|
||||
NSArray* models = [dictionary objectForKey:@"models"];
|
||||
[dictionary release];
|
||||
|
||||
|
||||
// NOTE: The models dictionary may contain NSManagedObjectID's from persistent objects
|
||||
// that were model mapped on a background thread. We look up the objects by ID and then
|
||||
// notify the delegate that the operation has completed.
|
||||
@@ -134,32 +149,32 @@
|
||||
[objects addObject:object];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[(NSObject<RKObjectLoaderDelegate>*)_delegate objectLoader:self didLoadObjects:[NSArray arrayWithArray:objects]];
|
||||
|
||||
|
||||
[self responseProcessingSuccessful:YES withError:nil];
|
||||
}
|
||||
|
||||
- (void)informDelegateOfObjectLoadErrorWithInfoDictionary:(NSDictionary*)dictionary {
|
||||
NSError* error = [dictionary objectForKey:@"error"];
|
||||
[dictionary release];
|
||||
|
||||
|
||||
NSLog(@"[RestKit] RKObjectLoader: Error saving managed object context: error=%@ userInfo=%@", error, error.userInfo);
|
||||
|
||||
|
||||
NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
[error localizedDescription], NSLocalizedDescriptionKey,
|
||||
nil];
|
||||
nil];
|
||||
NSError *rkError = [NSError errorWithDomain:RKRestKitErrorDomain code:RKObjectLoaderRemoteSystemError userInfo:userInfo];
|
||||
|
||||
|
||||
[(NSObject<RKObjectLoaderDelegate>*)_delegate objectLoader:self didFailWithError:rkError];
|
||||
|
||||
|
||||
[self responseProcessingSuccessful:NO withError:rkError];
|
||||
}
|
||||
|
||||
- (void)processLoadModelsInBackground:(RKResponse *)response {
|
||||
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
||||
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
||||
RKManagedObjectStore* objectStore = self.managedObjectStore;
|
||||
|
||||
|
||||
/**
|
||||
* If this loader is bound to a particular object, then we map
|
||||
* the results back into the instance. This is used for loading and updating
|
||||
@@ -188,12 +203,12 @@
|
||||
// so that in the event result is nil, then we get empty array instead of exception for trying to insert nil.
|
||||
results = [NSArray arrayWithObjects:result, nil];
|
||||
}
|
||||
|
||||
|
||||
if (objectStore && [objectStore managedObjectCache]) {
|
||||
if ([self.URL isKindOfClass:[RKURL class]]) {
|
||||
RKURL* rkURL = (RKURL*)self.URL;
|
||||
NSArray* fetchRequests = [[objectStore managedObjectCache] fetchRequestsForResourcePath:rkURL.resourcePath];
|
||||
NSArray* cachedObjects = [RKManagedObject objectsWithFetchRequests:fetchRequests];
|
||||
NSArray* cachedObjects = [RKManagedObject objectsWithFetchRequests:fetchRequests];
|
||||
for (id object in cachedObjects) {
|
||||
if ([object isKindOfClass:[RKManagedObject class]]) {
|
||||
if (NO == [results containsObject:object]) {
|
||||
@@ -204,15 +219,15 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Before looking up NSManagedObjectIDs, need to save to ensure we do not have
|
||||
// temporary IDs for new objects prior to handing the objectIDs across threads
|
||||
NSError* error = [objectStore save];
|
||||
if (nil != error) {
|
||||
NSDictionary* infoDictionary = [[NSDictionary dictionaryWithObjectsAndKeys:response, @"response", error, @"error", nil] retain];
|
||||
[self performSelectorOnMainThread:@selector(informDelegateOfObjectLoadErrorWithInfoDictionary:) withObject:infoDictionary waitUntilDone:YES];
|
||||
[self performSelectorOnMainThread:@selector(informDelegateOfObjectLoadErrorWithInfoDictionary:) withObject:infoDictionary waitUntilDone:YES];
|
||||
} else {
|
||||
// NOTE: Passing Core Data objects across threads is not safe.
|
||||
// NOTE: Passing Core Data objects across threads is not safe.
|
||||
// Iterate over each model and coerce Core Data objects into ID's to pass across the threads.
|
||||
// The object ID's will be deserialized back into objects on the main thread before the delegate is called back
|
||||
NSMutableArray* models = [NSMutableArray arrayWithCapacity:[results count]];
|
||||
@@ -220,10 +235,10 @@
|
||||
if ([object isKindOfClass:[NSManagedObject class]]) {
|
||||
[models addObject:[(NSManagedObject*)object objectID]];
|
||||
} else {
|
||||
[models addObject:object];
|
||||
[models addObject:object];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
NSDictionary* infoDictionary = [[NSDictionary dictionaryWithObjectsAndKeys:response, @"response", models, @"models", nil] retain];
|
||||
[self performSelectorOnMainThread:@selector(informDelegateOfObjectLoadWithInfoDictionary:) withObject:infoDictionary waitUntilDone:YES];
|
||||
}
|
||||
@@ -235,19 +250,19 @@
|
||||
if ([_delegate respondsToSelector:@selector(request:didFailLoadWithError:)]) {
|
||||
[_delegate request:self didFailLoadWithError:error];
|
||||
}
|
||||
|
||||
|
||||
[(NSObject<RKObjectLoaderDelegate>*)_delegate objectLoader:self didFailWithError:error];
|
||||
|
||||
|
||||
[self responseProcessingSuccessful:NO withError:error];
|
||||
}
|
||||
|
||||
- (void)didFinishLoad:(RKResponse*)response {
|
||||
_response = [response retain];
|
||||
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(request:didLoadResponse:)]) {
|
||||
[_delegate request:self didLoadResponse:response];
|
||||
}
|
||||
|
||||
|
||||
if (NO == [self encounteredErrorWhileProcessingRequest:response]) {
|
||||
// TODO: When other mapping formats are supported, unwind this assumption...
|
||||
if ([response isSuccessful] && [response isJSON]) {
|
||||
@@ -256,7 +271,7 @@
|
||||
NSLog(@"Encountered unexpected response code: %d (MIME Type: %@)", response.statusCode, response.MIMEType);
|
||||
if ([_delegate respondsToSelector:@selector(objectLoaderDidLoadUnexpectedResponse:)]) {
|
||||
[(NSObject<RKObjectLoaderDelegate>*)_delegate objectLoaderDidLoadUnexpectedResponse:self];
|
||||
}
|
||||
}
|
||||
[self responseProcessingSuccessful:NO withError:nil];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user