diff --git a/Code/ObjectMapping/RKObjectLoader.h b/Code/ObjectMapping/RKObjectLoader.h index e14e4949..2705a0de 100644 --- a/Code/ObjectMapping/RKObjectLoader.h +++ b/Code/ObjectMapping/RKObjectLoader.h @@ -36,6 +36,7 @@ RKResponse* _response; Class _objectClass; NSFetchRequest* _fetchRequest; + NSString* _keyPath; } /** @@ -96,6 +97,12 @@ */ @property (nonatomic, retain) NSFetchRequest* fetchRequest; +/* + * The keyPath property is an optional property to tell the mapper to map a subset of the response + * defined by a specific key. + */ +@property (nonatomic, copy) NSString* keyPath; + /** * Return an auto-released loader with with an object mapper, a request, and a delegate */ diff --git a/Code/ObjectMapping/RKObjectLoader.m b/Code/ObjectMapping/RKObjectLoader.m index 59a3a57d..ee49d345 100644 --- a/Code/ObjectMapping/RKObjectLoader.m +++ b/Code/ObjectMapping/RKObjectLoader.m @@ -20,7 +20,7 @@ @synthesize mapper = _mapper, delegate = _delegate, fetchRequest = _fetchRequest, request = _request, response = _response, objectClass = _objectClass, - source = _source; + source = _source, keyPath = _keyPath; + (id)loaderWithMapper:(RKObjectMapper*)mapper request:(RKRequest*)request delegate:(NSObject*)delegate { return [[[self alloc] initWithMapper:mapper request:request delegate:delegate] autorelease]; @@ -42,6 +42,7 @@ [_request release]; [_response release]; [_fetchRequest release]; + [_keyPath release]; [super dealloc]; } @@ -176,7 +177,7 @@ } } else { - id result = [_mapper mapFromString:[response bodyAsString] toClass:self.objectClass]; + id result = [_mapper mapFromString:[response bodyAsString] toClass:self.objectClass keyPath:_keyPath]; if ([result isKindOfClass:[NSArray class]]) { results = (NSArray*)result; } else { diff --git a/Code/ObjectMapping/RKObjectManager.m b/Code/ObjectMapping/RKObjectManager.m index b686d64f..beff39e5 100644 --- a/Code/ObjectMapping/RKObjectManager.m +++ b/Code/ObjectMapping/RKObjectManager.m @@ -108,6 +108,7 @@ static RKObjectManager* globalManager = nil; NSURL* URL = [self.client URLForResourcePath:resourcePath]; RKRequest* request = [[[RKRequest alloc] initWithURL:URL] autorelease]; + [self.client setupRequest:request]; RKObjectLoader* loader = [RKObjectLoader loaderWithMapper:self.mapper request:request delegate:delegate]; loader.objectClass = objectClass; diff --git a/Code/ObjectMapping/RKObjectMapper.m b/Code/ObjectMapping/RKObjectMapper.m index 61db86e2..19bd3266 100644 --- a/Code/ObjectMapping/RKObjectMapper.m +++ b/Code/ObjectMapping/RKObjectMapper.m @@ -101,8 +101,11 @@ static const NSString* kRKModelMapperMappingFormatParserKey = @"RKMappingFormatP return result; } -- (id)mapFromString:(NSString*)string toClass:(Class)class { +- (id)mapFromString:(NSString*)string toClass:(Class)class keyPath:(NSString*)keyPath { id object = [self parseString:string]; + if (keyPath) { + object = [object valueForKeyPath:keyPath]; + } if ([object isKindOfClass:[NSDictionary class]]) { return [self mapObjectFromDictionary:(NSDictionary*)object]; } else if ([object isKindOfClass:[NSArray class]]) { diff --git a/Code/Three20/RKRequestFilterableTTModel.h b/Code/Three20/RKRequestFilterableTTModel.h index 39a19980..669afb03 100644 --- a/Code/Three20/RKRequestFilterableTTModel.h +++ b/Code/Three20/RKRequestFilterableTTModel.h @@ -7,7 +7,7 @@ // #import "RKRequestTTModel.h" -#import +#import "RKSearchEngine.h" /** * Provides an interface for searching and filtering a collection diff --git a/Code/Three20/RKRequestModel.h b/Code/Three20/RKRequestModel.h index 0db011e8..2991e366 100644 --- a/Code/Three20/RKRequestModel.h +++ b/Code/Three20/RKRequestModel.h @@ -7,6 +7,7 @@ // #import +#import "../CoreData/RKManagedObject.h" /** * Lifecycle events for RKRequestModel @@ -31,9 +32,12 @@ NSString* _resourcePath; NSDictionary* _params; - RKRequest* _loadingRequest; RKRequestMethod _method; id _delegate; + RKObjectLoader* _objectLoader; + Class _objectClass; + NSString* _keyPath; + NSFetchRequest* _fetchRequest; NSTimeInterval _refreshRate; @@ -53,6 +57,7 @@ */ @property (nonatomic, readonly) NSDictionary* params; +@property (nonatomic, readonly) RKObjectLoader* objectLoader; @property (nonatomic, readonly) RKRequest* loadingRequest; /** @@ -70,8 +75,12 @@ */ + (id)modelWithResourcePath:(NSString*)resourcePath delegate:(id)delegate; + (id)modelWithResourcePath:(NSString*)resourcePath params:(NSDictionary*)params delegate:(id)delegate; ++ (id)modelWithResourcePath:(NSString*)resourcePath params:(NSDictionary*)params objectClass:(Class)klass delegate:(id)delegate; ++ (id)modelWithResourcePath:(NSString*)resourcePath params:(NSDictionary*)params objectClass:(Class)klass keyPath:(NSString*)keyPath delegate:(id)delegate; - (id)initWithResourcePath:(NSString*)resourcePath delegate:(id)delegate; - (id)initWithResourcePath:(NSString*)resourcePath params:(NSDictionary*)params delegate:(id)delegate; +- (id)initWithResourcePath:(NSString*)resourcePath params:(NSDictionary*)params objectClass:(Class)klass delegate:(id)delegate; +- (id)initWithResourcePath:(NSString*)resourcePath params:(NSDictionary*)params objectClass:(Class)klass keyPath:(NSString*)keyPath delegate:(id)delegate; /** * Clear the last loaded time for the model diff --git a/Code/Three20/RKRequestModel.m b/Code/Three20/RKRequestModel.m index 3639fc9a..89e67117 100644 --- a/Code/Three20/RKRequestModel.m +++ b/Code/Three20/RKRequestModel.m @@ -14,7 +14,7 @@ @synthesize loaded = _loaded; @synthesize resourcePath = _resourcePath; @synthesize params = _params; -@synthesize loadingRequest = _loadingRequest; +@synthesize objectLoader = _objectLoader; @synthesize method = _method; @synthesize fetchRequest = _fetchRequest; @synthesize refreshRate = _refreshRate; @@ -27,6 +27,14 @@ return [[[self alloc] initWithResourcePath:resourcePath params:params delegate:delegate] autorelease]; } ++ (id)modelWithResourcePath:(NSString*)resourcePath params:(NSDictionary*)params objectClass:(Class)klass delegate:(id)delegate { + return [[[self alloc] initWithResourcePath:resourcePath params:params objectClass:klass delegate:delegate] autorelease]; +} + ++ (id)modelWithResourcePath:(NSString*)resourcePath params:(NSDictionary*)params objectClass:(Class)klass keyPath:(NSString*)keyPath delegate:(id)delegate { + return [[[self alloc] initWithResourcePath:resourcePath params:params objectClass:klass keyPath:keyPath delegate:delegate] autorelease]; +} + - (id)initWithResourcePath:(NSString*)resourcePath delegate:(id)delegate { if (self = [self init]) { _resourcePath = [resourcePath retain]; @@ -46,18 +54,35 @@ return self; } +- (id)initWithResourcePath:(NSString*)resourcePath params:(NSDictionary*)params objectClass:(Class)klass delegate:(id)delegate { + if (self = [self init]) { + _resourcePath = [resourcePath retain]; + _params = [params retain]; + _delegate = [delegate retain]; + _objectClass = [klass retain]; + } + + return self; +} + +- (id)initWithResourcePath:(NSString*)resourcePath params:(NSDictionary*)params objectClass:(Class)klass keyPath:(NSString*)keyPath delegate:(id)delegate { + if (self = [self init]) { + _resourcePath = [resourcePath retain]; + _params = [params retain]; + _delegate = [delegate retain]; + _objectClass = [klass retain]; + _keyPath = [keyPath 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; @@ -65,14 +90,13 @@ - (void)dealloc { [_delegate release]; - [_loadingRequest cancel]; - [_loadingRequest release]; - _loadingRequest = nil; + [_objectLoader.request cancel]; + [_objectLoader release]; [_params release]; - _params = nil; [_objects release]; - _objects = nil; [_fetchRequest release]; + [_objectClass release]; + [_keyPath release]; [super dealloc]; } @@ -90,19 +114,16 @@ if ([_delegate respondsToSelector:@selector(rkModelDidFinishLoad)]) { [_delegate rkModelDidFinishLoad]; } - [_loadingRequest release];_loadingRequest=nil; } -// TODO: I get replaced... +//// 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]; } @@ -198,16 +219,22 @@ // 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)object { +- (void)objectLoader:(RKObjectLoader *)objectLoader didLoadObjects:(NSArray *)objects { + NSLog(@"Response: %@", [objectLoader.response bodyAsJSON]); +// [objectLoader.mapper mapFromString:[objectLoader.response bodyAsString]]; +// NSLog(@"Map: %@", [objectLoader.mapper mapFromString:[objectLoader.response bodyAsString]]); + NSLog(@"Objects: %@", objects); [self modelsDidLoad:objects]; + [objectLoader release]; } -- (void)resourceLoadRequest:(RKRequest*)request didFailWithError:(NSError*)error response:(RKResponse*)response object:(id)object { +- (void)objectLoader:(RKObjectLoader *)objectLoader didFailWithError:(NSError *)error { if ([self errorWarrantsOptionToGoOffline:error]) { [self showAlertWithOptionToGoOfflineForError:error]; } else { [_delegate didFailLoadWithError:error]; } + [objectLoader release]; } /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -224,11 +251,15 @@ } - (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]; - } + _objectLoader = [[[RKObjectManager globalManager] loaderWithResourcePath:_resourcePath objectClass:_objectClass delegate:self] retain]; + _objectLoader.method = _method; + _objectLoader.keyPath = _keyPath; + _objectLoader.params = _params; + [_objectLoader send]; +} + +- (RKRequest*)loadingRequest { + return _objectLoader.request; } @end diff --git a/Code/Three20/RKRequestTTModel.h b/Code/Three20/RKRequestTTModel.h index 1e04a5d7..182c0faf 100644 --- a/Code/Three20/RKRequestTTModel.h +++ b/Code/Three20/RKRequestTTModel.h @@ -7,7 +7,7 @@ // #import -#import "RestKit.h" +#import #import "RKRequestModel.h" /** @@ -22,8 +22,12 @@ + (id)modelWithResourcePath:(NSString*)resourcePath; + (id)modelWithResourcePath:(NSString*)resourcePath params:(NSDictionary*)params; ++ (id)modelWithResourcePath:(NSString*)resourcePath params:(NSDictionary*)params objectClass:(Class)klass; ++ (id)modelWithResourcePath:(NSString*)resourcePath params:(NSDictionary*)params objectClass:(Class)klass keyPath:(NSString*)keyPath; - (id)initWithResourcePath:(NSString*)resourcePath; - (id)initWithResourcePath:(NSString*)resourcePath params:(NSDictionary*)params; +- (id)initWithResourcePath:(NSString*)resourcePath params:(NSDictionary*)params objectClass:(Class)klass; +- (id)initWithResourcePath:(NSString*)resourcePath params:(NSDictionary*)params objectClass:(Class)klass keyPath:(NSString*)keyPath; - (NSArray*)objects; diff --git a/Code/Three20/RKRequestTTModel.m b/Code/Three20/RKRequestTTModel.m index f8072cce..0db2c2d8 100644 --- a/Code/Three20/RKRequestTTModel.m +++ b/Code/Three20/RKRequestTTModel.m @@ -20,6 +20,14 @@ return [[[self alloc] initWithResourcePath:resourcePath params:params] autorelease]; } ++ (id)modelWithResourcePath:(NSString*)resourcePath params:(NSDictionary*)params objectClass:(Class)klass{ + return [[[self alloc] initWithResourcePath:resourcePath params:params objectClass:klass] autorelease]; +} + ++ (id)modelWithResourcePath:(NSString*)resourcePath params:(NSDictionary*)params objectClass:(Class)klass keyPath:(NSString*)keyPath { + return [[[self alloc] initWithResourcePath:resourcePath params:params objectClass:klass keyPath:keyPath] autorelease]; +} + - (id)initWithResourcePath:(NSString*)resourcePath { if (self = [self init]) { _model = [[RKRequestModel modelWithResourcePath:resourcePath delegate:self] retain]; @@ -34,6 +42,20 @@ return self; } +- (id)initWithResourcePath:(NSString*)resourcePath params:(NSDictionary*)params objectClass:(Class)klass{ + if (self = [self init]) { + _model = [[RKRequestModel modelWithResourcePath:resourcePath params:params objectClass:klass delegate:self] retain]; + } + return self; +} + +- (id)initWithResourcePath:(NSString*)resourcePath params:(NSDictionary*)params objectClass:(Class)klass keyPath:(NSString*)keyPath { + if (self = [self init]) { + _model = [[RKRequestModel modelWithResourcePath:resourcePath params:params objectClass:klass keyPath:keyPath delegate:self] retain]; + } + return self; +} + /////////////////////////////////////////////////////////////////////////////////////////////////// // NSObject diff --git a/Code/Three20/Three20.h b/Code/Three20/Three20.h index 1fe24188..01194d0c 100644 --- a/Code/Three20/Three20.h +++ b/Code/Three20/Three20.h @@ -6,6 +6,6 @@ // Copyright 2010 Two Toasters. All rights reserved. // -#import "Three20/RKRequestModel.h" -#import "Three20/RKRequestTTModel.h" -#import "Three20/RKRequestFilterableTTModel.h" +#import "RKRequestModel.h" +#import "RKRequestTTModel.h" +#import "RKRequestFilterableTTModel.h"