removed duplicate delegates on RKObjectLoader; inverted control for communicating request completion from RKResponse to RKRequest; added state tracking to RKRequest for loaded and loading states; changed queue processing logic to check request states before firing new requests; removed retains of RKObjectLoader from RKRequestTTModel since our queue is handling retains for all asynchronous RKRequest flavors; added separate state tracking to RKRequestTTModel since there are subtle differences between the meaning of loaded/loading in Three20 versus our RKRequest states; removed delegate forwarding code from RKObjectLoader since it is no longer an RKRequestDelegate (which was quite ugly to begin with); removed unnecessary error contructor for RKResponse that was only being used to fire delegate callbacks when an RKRequest failed to fire in offline mode; added TODOs to deep-dive into synchronous request handling

This commit is contained in:
Jeff Arena
2010-12-02 13:22:38 -08:00
parent 6249ece2bc
commit c9ba879937
9 changed files with 171 additions and 155 deletions

View File

@@ -35,6 +35,8 @@ typedef enum RKRequestMethod {
NSString* _username;
NSString* _password;
RKRequestMethod _method;
BOOL _isLoading;
BOOL _isLoaded;
}
/**
@@ -123,6 +125,18 @@ typedef enum RKRequestMethod {
*/
- (RKResponse*)sendSynchronously;
/**
* Callback performed to notify the request that the underlying NSURLConnection
* has failed with an error.
*/
- (void)didFailLoadWithError:(NSError*)error;
/**
* Callback performed to notify the request that the underlying NSURLConnection
* has completed with a response.
*/
- (void)didFinishLoad:(RKResponse*)response;
/**
* Cancels the underlying URL connection
*/
@@ -148,6 +162,16 @@ typedef enum RKRequestMethod {
*/
- (BOOL)isDELETE;
/**
* Returns YES when this request is in-progress
*/
- (BOOL)isLoading;
/**
* Returns YES when this request has been completed
*/
- (BOOL)isLoaded;
@end
/**

View File

@@ -21,10 +21,7 @@
params = _params, userData = _userData, username = _username, password = _password, method = _method;
+ (RKRequest*)requestWithURL:(NSURL*)URL delegate:(id)delegate {
RKRequest* request = [[RKRequest alloc] initWithURL:URL delegate:delegate];
[request autorelease];
return request;
return [[[RKRequest alloc] initWithURL:URL delegate:delegate] autorelease];
}
- (id)initWithURL:(NSURL*)URL {
@@ -32,8 +29,9 @@
_URL = [URL retain];
_URLRequest = [[NSMutableURLRequest alloc] initWithURL:_URL];
_connection = nil;
_isLoading = NO;
_isLoaded = NO;
}
return self;
}
@@ -41,20 +39,28 @@
if (self = [self initWithURL:URL]) {
_delegate = delegate;
}
return self;
}
- (void)dealloc {
self.delegate = nil;
[_connection cancel];
[_connection release];
_connection = nil;
[_userData release];
_userData = nil;
[_URL release];
_URL = nil;
[_URLRequest release];
_URLRequest = nil;
[_params release];
_params = nil;
[_additionalHTTPHeaders release];
_additionalHTTPHeaders = nil;
[_username release];
_username = nil;
[_password release];
_password = nil;
[super dealloc];
}
@@ -131,6 +137,7 @@
NSDictionary* userInfo = [NSDictionary dictionaryWithObjectsAndKeys:[self HTTPMethod], @"HTTPMethod", [self URL], @"URL", sentAt, @"sentAt", nil];
[[NSNotificationCenter defaultCenter] postNotificationName:kRKRequestSentNotification object:self userInfo:userInfo];
_isLoading = YES;
RKResponse* response = [[[RKResponse alloc] initWithRequest:self] autorelease];
_connection = [[NSURLConnection connectionWithRequest:_URLRequest delegate:response] retain];
} else {
@@ -139,7 +146,7 @@
errorMessage, NSLocalizedDescriptionKey,
nil];
NSError* error = [NSError errorWithDomain:RKRestKitErrorDomain code:RKRequestBaseURLOfflineError userInfo:userInfo];
RKResponse* response = [[[RKResponse alloc] initWithRequest:self error:error] autorelease];
[self didFailLoadWithError:error];
}
}
@@ -158,6 +165,7 @@
NSDictionary* userInfo = [NSDictionary dictionaryWithObjectsAndKeys:[self HTTPMethod], @"HTTPMethod", [self URL], @"URL", sentAt, @"sentAt", nil];
[[NSNotificationCenter defaultCenter] postNotificationName:kRKRequestSentNotification object:self userInfo:userInfo];
_isLoading = YES;
payload = [NSURLConnection sendSynchronousRequest:_URLRequest returningResponse:&URLResponse error:&error];
response = [[[RKResponse alloc] initWithSynchronousRequest:self URLResponse:URLResponse body:payload error:error] autorelease];
} else {
@@ -166,6 +174,9 @@
errorMessage, NSLocalizedDescriptionKey,
nil];
error = [NSError errorWithDomain:RKRestKitErrorDomain code:RKRequestBaseURLOfflineError userInfo:userInfo];
[self didFailLoadWithError:error];
// TODO: Is this needed here? Or can we just return a nil response and everyone will be happy??
response = [[[RKResponse alloc] initWithSynchronousRequest:self URLResponse:URLResponse body:payload error:error] autorelease];
}
@@ -176,6 +187,33 @@
[_connection cancel];
[_connection release];
_connection = nil;
_isLoading = NO;
}
- (void)didFailLoadWithError:(NSError*)error {
_isLoading = NO;
if ([_delegate respondsToSelector:@selector(request:didFailLoadWithError:)]) {
[_delegate request:self didFailLoadWithError:error];
}
NSDate* receivedAt = [NSDate date];
NSDictionary* userInfo = [NSDictionary dictionaryWithObjectsAndKeys:[self HTTPMethod], @"HTTPMethod",
[self URL], @"URL", receivedAt, @"receivedAt", error, @"error", nil];
[[NSNotificationCenter defaultCenter] postNotificationName:kRKRequestFailedWithErrorNotification object:self userInfo:userInfo];
}
- (void)didFinishLoad:(RKResponse*)response {
_isLoading = NO;
_isLoaded = YES;
if ([_delegate respondsToSelector:@selector(requestDidFinishLoad:withResponse:)]) {
[_delegate requestDidFinishLoad:self withResponse:response];
}
NSDate* receivedAt = [NSDate date];
NSDictionary* userInfo = [NSDictionary dictionaryWithObjectsAndKeys:[self HTTPMethod], @"HTTPMethod", [self URL], @"URL", receivedAt, @"receivedAt", nil];
[[NSNotificationCenter defaultCenter] postNotificationName:kRKResponseReceivedNotification object:response userInfo:userInfo];
}
- (BOOL)isGET {
@@ -194,6 +232,14 @@
return _method == RKRequestMethodDELETE;
}
- (BOOL)isLoading {
return _isLoading;
}
- (BOOL)isLoaded {
return _isLoaded;
}
- (NSString*)resourcePath {
NSString* resourcePath = nil;
if ([self.URL isKindOfClass:[RKURL class]]) {

View File

@@ -76,12 +76,11 @@ static const NSInteger kMaxConcurrentLoads = 5;
- (void)loadNextInQueue {
_queueTimer = nil;
for (int i = _totalLoading;
i < kMaxConcurrentLoads && i < _requests.count;
++i) {
RKRequest* request = [_requests objectAtIndex:i];
++_totalLoading;
[self dispatchRequest:request];
for (RKRequest* request in _requests) {
if (![request isLoading] && ![request isLoaded] && _totalLoading < kMaxConcurrentLoads) {
++_totalLoading;
[self dispatchRequest:request];
}
}
if (_requests.count && !_suspended) {
@@ -106,27 +105,36 @@ static const NSInteger kMaxConcurrentLoads = 5;
[self loadNextInQueue];
}
- (void)cancelRequest:(RKRequest*)request {
if ([_requests containsObject:request]) {
- (void)cancelRequest:(RKRequest*)request loadNext:(BOOL)loadNext {
if ([_requests containsObject:request] && ![request isLoaded]) {
[request cancel];
NSLog(@"Request cancelled and removed: URL=%@", [request URL]);
[_requests removeObject:request];
_totalLoading--;
[self loadNextInQueue];
if (loadNext) {
[self loadNextInQueue];
}
}
}
- (void)cancelRequest:(RKRequest*)request {
[self cancelRequest:request loadNext:YES];
}
- (void)cancelRequestsWithDelegate:(NSObject<RKRequestDelegate>*)delegate {
for (RKRequest* request in _requests) {
if (request.delegate && request.delegate == delegate) {
[request cancel];
[self cancelRequest:request];
}
}
}
- (void)cancelAllRequests {
for (RKRequest* request in [[[_requests copy] autorelease] objectEnumerator]) {
[request cancel];
[self cancelRequest:request loadNext:NO];
}
}
@@ -137,9 +145,6 @@ static const NSInteger kMaxConcurrentLoads = 5;
- (void)responseDidLoad:(NSNotification*)notification {
if (notification.object && [notification.object isKindOfClass:[RKResponse class]]) {
RKResponse* response = (RKResponse*)notification.object;
[_requests removeObject:[response request]];
_totalLoading--;
[self loadNextInQueue];
NSError* error = (NSError*)[notification.userInfo objectForKey:@"error"];
if (error) {
@@ -147,6 +152,11 @@ static const NSInteger kMaxConcurrentLoads = 5;
} else {
NSLog(@"Request completed and removed: URL=%@", [[response request] URL]);
}
[_requests removeObject:[response request]];
_totalLoading--;
[self loadNextInQueue];
}
}

View File

@@ -57,13 +57,6 @@
*/
- (id)initWithRequest:(RKRequest*)request;
/**
* Initialize a new response object for a REST request along
* with an error object, allowing for failures prior to an asynchronous
* request being sent.
*/
- (id)initWithRequest:(RKRequest*)request error:(NSError*)error;
/**
* Initializes a response object from the results of a synchronous request
*/

View File

@@ -34,20 +34,11 @@
return self;
}
- (id)initWithRequest:(RKRequest*)request error:(NSError*)error {
if (self = [self initWithRequest:request]) {
_failureError = [error retain];
if ([[_request delegate] respondsToSelector:@selector(request:didFailLoadWithError:)]) {
[[_request delegate] request:_request didFailLoadWithError:error];
}
}
return self;
}
- (id)initWithSynchronousRequest:(RKRequest*)request URLResponse:(NSURLResponse*)URLResponse body:(NSData*)body error:(NSError*)error {
if (self = [super init]) {
_request = [request retain];
// TODO: Does the lack of retain here cause problems with synchronous requests, since they
// are not being retained by the RKRequestQueue??
_request = request;
_httpURLResponse = [URLResponse retain];
_failureError = [error retain];
_body = [body retain];
@@ -94,25 +85,12 @@
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
if ([[_request delegate] respondsToSelector:@selector(requestDidFinishLoad:withResponse:)]) {
[[_request delegate] requestDidFinishLoad:_request withResponse:self];
}
NSDate* receivedAt = [NSDate date];
NSDictionary* userInfo = [NSDictionary dictionaryWithObjectsAndKeys:[_request HTTPMethod], @"HTTPMethod", [_request URL], @"URL", receivedAt, @"receivedAt", nil];
[[NSNotificationCenter defaultCenter] postNotificationName:kRKResponseReceivedNotification object:self userInfo:userInfo];
[_request didFinishLoad:self];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
_failureError = [error retain];
if ([[_request delegate] respondsToSelector:@selector(request:didFailLoadWithError:)]) {
[[_request delegate] request:_request didFailLoadWithError:error];
}
NSDate* receivedAt = [NSDate date];
NSDictionary* userInfo = [NSDictionary dictionaryWithObjectsAndKeys:[_request HTTPMethod], @"HTTPMethod",
[_request URL], @"URL", receivedAt, @"receivedAt", error, @"error", nil];
[[NSNotificationCenter defaultCenter] postNotificationName:kRKRequestFailedWithErrorNotification object:_request userInfo:userInfo];
[_request didFailLoadWithError:_failureError];
}
- (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite {

View File

@@ -40,9 +40,8 @@
/**
* Wraps a request/response cycle and loads a remote object representation into local domain objects
*/
@interface RKObjectLoader : RKRequest <RKRequestDelegate> {
@interface RKObjectLoader : RKRequest {
RKObjectMapper* _mapper;
NSObject<RKObjectLoaderDelegate>* _objectLoaderDelegate;
RKResponse* _response;
NSObject<RKObjectMappable>* _targetObject;
Class<RKObjectMappable> _objectClass;
@@ -56,14 +55,6 @@
*/
@property (nonatomic, readonly) RKObjectMapper* mapper;
/**
* The object to be invoked with the loaded models
*
* If this object implements life-cycle methods from the RKRequestDelegate protocol,
* events from the request will be forwarded back.
*/
@property (nonatomic, assign) NSObject<RKObjectLoaderDelegate>* objectLoaderDelegate;
/**
* The underlying response object for this loader
*/

View File

@@ -13,24 +13,20 @@
#import "Errors.h"
#import "RKManagedObject.h"
#import "RKURL.h"
@interface RKObjectLoader (Private)
- (void)loadObjectsFromResponse:(RKResponse*)response;
@end
#import "RKNotifications.h"
@implementation RKObjectLoader
@synthesize mapper = _mapper, objectLoaderDelegate = _objectLoaderDelegate, response = _response,
objectClass = _objectClass, targetObject = _targetObject, keyPath = _keyPath, managedObjectStore = _managedObjectStore;
@synthesize mapper = _mapper, response = _response, objectClass = _objectClass, targetObject = _targetObject,
keyPath = _keyPath, managedObjectStore = _managedObjectStore;
+ (id)loaderWithResourcePath:(NSString*)resourcePath mapper:(RKObjectMapper*)mapper delegate:(NSObject<RKObjectLoaderDelegate>*)delegate {
return [[[self alloc] initWithResourcePath:resourcePath mapper:mapper delegate:delegate] autorelease];
}
- (id)initWithResourcePath:(NSString*)resourcePath mapper:(RKObjectMapper*)mapper delegate:(NSObject<RKObjectLoaderDelegate>*)delegate {
if (self = [self initWithURL:[[RKClient sharedClient] URLForResourcePath:resourcePath] delegate:self]) {
if (self = [self initWithURL:[[RKClient sharedClient] URLForResourcePath:resourcePath] delegate:delegate]) {
_mapper = [mapper retain];
self.objectLoaderDelegate = delegate;
self.managedObjectStore = nil;
_targetObjectID = nil;
@@ -40,15 +36,17 @@
}
- (void)dealloc {
self.delegate = nil;
self.objectLoaderDelegate = nil;
[self cancel];
[_mapper release];
_mapper = nil;
[_response release];
_response = nil;
[_keyPath release];
self.managedObjectStore = nil;
_keyPath = nil;
[_targetObject release];
_targetObject = nil;
[_targetObjectID release];
_targetObjectID = nil;
_targetObjectID = nil;
self.managedObjectStore = nil;
[super dealloc];
}
@@ -68,16 +66,25 @@
#pragma mark Response Processing
- (void)responseProcessingComplete {
_isLoading = NO;
_isLoaded = YES;
NSDate* receivedAt = [NSDate date];
NSDictionary* userInfo = [NSDictionary dictionaryWithObjectsAndKeys:[self HTTPMethod], @"HTTPMethod", [self URL], @"URL", receivedAt, @"receivedAt", nil];
[[NSNotificationCenter defaultCenter] postNotificationName:kRKResponseReceivedNotification object:_response userInfo:userInfo];
}
- (BOOL)encounteredErrorWhileProcessingRequest:(RKResponse*)response {
if ([response isFailure]) {
[_objectLoaderDelegate objectLoader:self didFailWithError:response.failureError];
[(NSObject<RKObjectLoaderDelegate>*)_delegate objectLoader:self didFailWithError:response.failureError];
return YES;
} else if ([response isError]) {
if ([response isJSON]) {
[_objectLoaderDelegate objectLoader:self didFailWithError:[_mapper parseErrorFromString:[response bodyAsString]]];
[(NSObject<RKObjectLoaderDelegate>*)_delegate objectLoader:self didFailWithError:[_mapper parseErrorFromString:[response bodyAsString]]];
} else {
if ([_objectLoaderDelegate respondsToSelector:@selector(objectLoaderDidLoadUnexpectedResponse:)]) {
[_objectLoaderDelegate objectLoaderDidLoadUnexpectedResponse:self];
if ([_delegate respondsToSelector:@selector(objectLoaderDidLoadUnexpectedResponse:)]) {
[(NSObject<RKObjectLoaderDelegate>*)_delegate objectLoaderDidLoadUnexpectedResponse:self];
}
}
return YES;
@@ -101,7 +108,9 @@
}
}
[_objectLoaderDelegate objectLoader:self didLoadObjects:[NSArray arrayWithArray:objects]];
[(NSObject<RKObjectLoaderDelegate>*)_delegate objectLoader:self didLoadObjects:[NSArray arrayWithArray:objects]];
[self responseProcessingComplete];
}
- (void)informDelegateOfObjectLoadErrorWithInfoDictionary:(NSDictionary*)dictionary {
@@ -115,7 +124,9 @@
nil];
NSError *rkError = [NSError errorWithDomain:RKRestKitErrorDomain code:RKObjectLoaderRemoteSystemError userInfo:userInfo];
[_objectLoaderDelegate objectLoader:self didFailWithError:rkError];
[(NSObject<RKObjectLoaderDelegate>*)_delegate objectLoader:self didFailWithError:rkError];
[self responseProcessingComplete];
}
@@ -190,46 +201,26 @@
[pool release];
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// RKRequestDelegate
//
// If our delegate responds to the messages, forward them back...
- (void)requestDidStartLoad:(RKRequest*)request {
if ([_objectLoaderDelegate respondsToSelector:@selector(requestDidStartLoad:)]) {
[_objectLoaderDelegate requestDidStartLoad:request];
}
}
- (void)requestDidFinishLoad:(RKRequest*)request withResponse:(RKResponse*)response {
- (void)didFinishLoad:(RKResponse*)response {
_response = [response retain];
if ([_delegate respondsToSelector:@selector(requestDidFinishLoad:withResponse:)]) {
[_delegate requestDidFinishLoad:self withResponse:response];
}
if (NO == [self encounteredErrorWhileProcessingRequest:response]) {
// TODO: When other mapping formats are supported, unwind this assumption...
if ([response isSuccessful] && [response isJSON]) {
[self performSelectorInBackground:@selector(processLoadModelsInBackground:) withObject:response];
} else {
NSLog(@"Encountered unexpected response code: %d (MIME Type: %@)", response.statusCode, response.MIMEType);
if ([_objectLoaderDelegate respondsToSelector:@selector(objectLoaderDidLoadUnexpectedResponse:)]) {
[_objectLoaderDelegate objectLoaderDidLoadUnexpectedResponse:self];
if ([_delegate respondsToSelector:@selector(objectLoaderDidLoadUnexpectedResponse:)]) {
[(NSObject<RKObjectLoaderDelegate>*)_delegate objectLoaderDidLoadUnexpectedResponse:self];
}
[self responseProcessingComplete];
}
}
if ([_objectLoaderDelegate respondsToSelector:@selector(requestDidFinishLoad:)]) {
[(NSObject<RKRequestDelegate>*)_objectLoaderDelegate requestDidFinishLoad:request withResponse:response];
}
}
- (void)request:(RKRequest*)request didFailLoadWithError:(NSError*)error {
if ([_objectLoaderDelegate respondsToSelector:@selector(request:didFailLoadWithError:)]) {
[(NSObject<RKRequestDelegate>*)_objectLoaderDelegate request:request didFailLoadWithError:error];
}
}
- (void)request:(RKRequest*)request didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite {
if ([_objectLoaderDelegate respondsToSelector:@selector(request:didSendBodyData:totalBytesWritten:totalBytesExpectedToWrite:)]) {
[(NSObject<RKRequestDelegate>*)_objectLoaderDelegate request:request didSendBodyData:bytesWritten totalBytesWritten:totalBytesWritten totalBytesExpectedToWrite:totalBytesExpectedToWrite];
} else {
[self responseProcessingComplete];
}
}

View File

@@ -15,13 +15,13 @@
*/
@interface RKRequestTTModel : TTModel <RKObjectLoaderDelegate> {
NSArray *_objects;
BOOL _loaded;
BOOL _isLoaded;
BOOL _isLoading;
BOOL _cacheLoaded;
NSString* _resourcePath;
NSDictionary* _params;
RKRequestMethod _method;
RKObjectLoader* _objectLoader;
Class _objectClass;
NSString* _keyPath;
@@ -38,12 +38,6 @@
*/
@property (nonatomic, readonly) NSString* resourcePath;
/**
* The RKObjectLoader, created when this model is loading data
* from the resourcePath.
*/
@property (nonatomic, readonly) RKObjectLoader* objectLoader;
/**
* The NSDate object representing the last time this model was loaded.
*/

View File

@@ -31,7 +31,6 @@ static NSString* const kDefaultLoadedTimeKey = @"RKRequestTTModelDefaultLoadedTi
@synthesize objects = _objects;
@synthesize resourcePath = _resourcePath;
@synthesize params = _params;
@synthesize objectLoader = _objectLoader;
@synthesize method = _method;
@synthesize refreshRate = _refreshRate;
@@ -97,18 +96,15 @@ static NSString* const kDefaultLoadedTimeKey = @"RKRequestTTModelDefaultLoadedTi
self.params = nil;
_cacheLoaded = NO;
_objects = nil;
_loaded = NO;
_isLoaded = NO;
_isLoading = NO;
_resourcePath = nil;
_objectLoader = nil;
}
return self;
}
- (void)dealloc {
[_objectLoader setObjectLoaderDelegate:nil];
[[RKRequestQueue sharedQueue] cancelRequest:_objectLoader];
[_objectLoader release];
_objectLoader = nil;
[[RKRequestQueue sharedQueue] cancelRequestsWithDelegate:self];
[_objects release];
_objects = nil;
[_objectClass release];
@@ -123,11 +119,11 @@ static NSString* const kDefaultLoadedTimeKey = @"RKRequestTTModelDefaultLoadedTi
// TTModel
- (BOOL)isLoaded {
return _loaded;
return _isLoaded;
}
- (BOOL)isLoading {
return nil != _objectLoader;
return _isLoading;
}
- (BOOL)isLoadingMore {
@@ -139,9 +135,7 @@ static NSString* const kDefaultLoadedTimeKey = @"RKRequestTTModelDefaultLoadedTi
}
- (void)cancel {
[[RKRequestQueue sharedQueue] cancelRequest:_objectLoader];
[_objectLoader release];
_objectLoader = nil;
[[RKRequestQueue sharedQueue] cancelRequestsWithDelegate:self];
[self didCancelLoad];
}
@@ -164,30 +158,24 @@ static NSString* const kDefaultLoadedTimeKey = @"RKRequestTTModelDefaultLoadedTi
#pragma mark RKModelLoaderDelegate
// This callback is invoked after the request has been fully serviced. Finish the load here.
- (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:(NSArray*)objects {
if (objectLoader == _objectLoader) {
[_objectLoader release];
_objectLoader = nil;
[self modelsDidLoad:objects];
}
_isLoading = NO;
[self modelsDidLoad:objects];
}
- (void)objectLoader:(RKObjectLoader*)objectLoader didFailWithError:(NSError*)error {
if (objectLoader == _objectLoader) {
[_objectLoader release];
_objectLoader = nil;
}
_isLoading = NO;
[self didFailLoadWithError:error];
if ([self errorWarrantsOptionToGoOffline:error]) {
[self showAlertWithOptionToGoOfflineForError:error];
} else {
[self didFailLoadWithError:error];
}
}
- (void)objectLoaderDidLoadUnexpectedResponse:(RKObjectLoader*)objectLoader {
[objectLoader release];
_objectLoader = nil;
_isLoading = NO;
// TODO: Passing a nil error here does nothing for Three20. Need to construct our
// own error here to make Three20 happy??
[self didFailLoadWithError:nil];
}
@@ -241,7 +229,7 @@ static NSString* const kDefaultLoadedTimeKey = @"RKRequestTTModelDefaultLoadedTi
_objects = nil;
_objects = models;
_loaded = YES;
_isLoaded = YES;
[self saveLoadedTime];
[self didFinishLoad];
@@ -260,14 +248,15 @@ static NSString* const kDefaultLoadedTimeKey = @"RKRequestTTModelDefaultLoadedTi
}
if (!store.managedObjectCache || !cacheFetchRequests || _cacheLoaded || [cachedObjects count] == 0) {
_objectLoader = [[[RKObjectManager sharedManager] objectLoaderWithResourcePath:_resourcePath delegate:self] retain];
_objectLoader.method = self.method;
_objectLoader.objectClass = _objectClass;
_objectLoader.keyPath = _keyPath;
_objectLoader.params = self.params;
RKObjectLoader* objectLoader = [[[RKObjectManager sharedManager] objectLoaderWithResourcePath:_resourcePath delegate:self] retain];
objectLoader.method = self.method;
objectLoader.objectClass = _objectClass;
objectLoader.keyPath = _keyPath;
objectLoader.params = self.params;
_isLoading = YES;
[self didStartLoad];
[_objectLoader send];
[objectLoader send];
} else if (cacheFetchRequests && !_cacheLoaded) {
_cacheLoaded = YES;