Files
RestKit/Code/Three20/RKRequestModel.m

235 lines
6.5 KiB
Objective-C

//
// RKRequestModel.m
// RestKit
//
// Created by Jeff Arena on 4/26/10.
// Copyright 2010 RestKit. All rights reserved.
//
#import "RKRequestModel.h"
#import <Three20/Three20.h>
@implementation RKRequestModel
@synthesize objects = _objects;
@synthesize loaded = _loaded;
@synthesize resourcePath = _resourcePath;
@synthesize params = _params;
@synthesize loadingRequest = _loadingRequest;
@synthesize method = _method;
@synthesize fetchRequest = _fetchRequest;
@synthesize refreshRate = _refreshRate;
+ (id)modelWithResourcePath:(NSString*)resourcePath delegate:(id)delegate {
return [[[self alloc] initWithResourcePath:resourcePath delegate:delegate] autorelease];
}
+ (id)modelWithResourcePath:(NSString*)resourcePath params:(NSDictionary*)params delegate:(id)delegate {
return [[[self alloc] initWithResourcePath:resourcePath params:params delegate:delegate] autorelease];
}
- (id)initWithResourcePath:(NSString*)resourcePath delegate:(id)delegate {
if (self = [self init]) {
_resourcePath = [resourcePath retain];
_delegate = [delegate retain];
}
return self;
}
- (id)initWithResourcePath:(NSString*)resourcePath params:(NSDictionary*)params delegate:(id)delegate {
if (self = [self init]) {
_resourcePath = [resourcePath retain];
_params = [params retain];
_delegate = [delegate retain];
}
return self;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// NSObject
- (id)init {
if (self = [super init]) {
_loadingRequest = nil;
_objects = nil;
_delegate = nil;
_params = nil;
_loaded = NO;
_method = RKRequestMethodGET;
_fetchRequest = nil;
_refreshRate = (60*60); // 1 hour default
}
return self;
}
- (void)dealloc {
[_delegate release];
[_loadingRequest cancel];
[_loadingRequest release];
_loadingRequest = nil;
[_params release];
_params = nil;
[_objects release];
_objects = nil;
[_fetchRequest release];
[super dealloc];
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// RKRequestDelegate
- (void)requestDidStartLoad:(RKRequest*)request {
if ([_delegate respondsToSelector:@selector(rkModelDidStartLoad)]) {
[_delegate rkModelDidStartLoad];
}
}
- (void)requestDidFinishLoad:(RKRequest*)request {
[self saveLoadedTime];
if ([_delegate respondsToSelector:@selector(rkModelDidFinishLoad)]) {
[_delegate rkModelDidFinishLoad];
}
[_loadingRequest release];_loadingRequest=nil;
}
// TODO: I get replaced...
- (void)request:(RKRequest*)request didFailLoadWithError:(NSError*)error {
[_loadingRequest release];_loadingRequest=nil;
if ([_delegate respondsToSelector:@selector(rkModelDidFailLoadWithError:)]) {
[_delegate rkModelDidFailLoadWithError:error];
}
}
- (void)requestDidCancelLoad:(RKRequest*)request {
[_loadingRequest release];_loadingRequest=nil;
if ([_delegate respondsToSelector:@selector(rkModelDidCancelLoad)]) {
[_delegate rkModelDidCancelLoad];
}
}
- (BOOL)needsRefresh {
NSDate* loadedTime = self.loadedTime;
if (loadedTime) {
BOOL outdated = -[loadedTime timeIntervalSinceNow] > _refreshRate;
return outdated;
}
return YES;
}
- (void)clearLoadedTime {
[[NSUserDefaults standardUserDefaults] removeObjectForKey:_resourcePath];
}
- (void)saveLoadedTime {
[[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:_resourcePath];
}
- (NSDate*)loadedTime {
return [[NSUserDefaults standardUserDefaults] objectForKey:_resourcePath];
}
- (void)loadFromObjectCache {
if (_fetchRequest != nil) {
if ([_delegate respondsToSelector:@selector(rkModelDidStartLoad)]) {
[_delegate rkModelDidStartLoad];
}
_objects = [[RKManagedObject objectsWithRequest:_fetchRequest] retain];
_loaded = YES;
if ([_delegate respondsToSelector:@selector(rkModelDidFinishLoad)]) {
[_delegate rkModelDidFinishLoad];
}
// TODO: What if self.needsRefresh does the update load???
if ([self needsRefresh]) {
[self load];
}
}
}
- (BOOL)errorWarrantsOptionToGoOffline:(NSError*)error {
switch ([error code]) {
case NSURLErrorTimedOut:
case NSURLErrorCannotFindHost:
case NSURLErrorCannotConnectToHost:
case NSURLErrorNetworkConnectionLost:
case NSURLErrorDNSLookupFailed:
case NSURLErrorNotConnectedToInternet:
case NSURLErrorInternationalRoamingOff:
return YES;
break;
default:
return NO;
break;
}
}
- (void)showAlertWithOptionToGoOfflineForError:(NSError*)error {
UIAlertView* alert = [[[UIAlertView alloc] initWithTitle:TTLocalizedString(@"Network Error", @"")
message:[error localizedDescription]
delegate:self
cancelButtonTitle:TTLocalizedString(@"OK", @"")
otherButtonTitles:TTLocalizedString(@"Go Offline", @""), nil] autorelease];
[alert show];
}
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
// Go Offline button
if (1 == buttonIndex) {
[[RKObjectManager globalManager] goOffline];
}
}
- (void)modelsDidLoad:(NSArray*)models {
[models retain];
[_objects release];
_objects = models;
_loaded = YES;
// NOTE: You must finish load after clearing the loadingRequest and setting the loaded flag
if ([_delegate respondsToSelector:@selector(rkModelDidLoad)]) {
[_delegate rkModelDidLoad];
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// RKModelLoaderDelegate
// This callback is invoked after the request has been fully serviced. Finish the load here.
- (void)resourceLoadRequest:(RKRequest *)request didLoadObjects:(NSArray *)objects response:(RKResponse *)response object:(id<RKObjectMappable>)object {
[self modelsDidLoad:objects];
}
- (void)resourceLoadRequest:(RKRequest*)request didFailWithError:(NSError*)error response:(RKResponse*)response object:(id<RKObjectMappable>)object {
if ([self errorWarrantsOptionToGoOffline:error]) {
[self showAlertWithOptionToGoOfflineForError:error];
} else {
[_delegate didFailLoadWithError:error];
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// public
- (void)setFetchRequest:(NSFetchRequest*)fetchRequest {
[_fetchRequest release];
_fetchRequest = [fetchRequest retain];
[self loadFromObjectCache];
}
- (void)reset {
[self clearLoadedTime];
}
- (void)load {
if (_params) {
_loadingRequest = [[RKObjectManager globalManager] loadResource:_resourcePath fetchRequest:_fetchRequest method:_method params:_params delegate:self];
} else {
_loadingRequest = [[RKObjectManager globalManager] loadResource:_resourcePath fetchRequest:_fetchRequest method:_method delegate:self];
}
}
@end