Finished cleaning up Core Data support. Happy with the new organization

This commit is contained in:
Blake Watters
2011-03-19 22:06:51 -04:00
parent 58f867160f
commit 2109fae1ba
16 changed files with 664 additions and 111 deletions

View File

@@ -7,10 +7,10 @@
//
#import "../Network/Network.h"
#import "RKObjectMapper.h"
#import "RKObjectMappable.h"
@class RKObjectManager;
@class RKObjectLoader;
@class RKManagedObjectStore;
@protocol RKObjectLoaderDelegate <RKRequestDelegate>
@@ -38,28 +38,24 @@
/**
* Wraps a request/response cycle and loads a remote object representation into local domain objects
*
* NOTE: When Core Data is linked into the application, the object manager will return instances of
* RKManagedObjectLoader instead of RKObjectLoader. RKManagedObjectLoader is a descendent class that
* includes Core Data specific mapping logic.
*/
@interface RKObjectLoader : RKRequest {
RKObjectMapper* _mapper;
@interface RKObjectLoader : RKRequest {
RKObjectManager* _objectManager;
RKResponse* _response;
NSObject<RKObjectMappable>* _targetObject;
Class<RKObjectMappable> _objectClass;
NSString* _keyPath;
RKManagedObjectStore* _managedObjectStore;
RKClient* _client; // TODO: Break linkage to RKClient using notifications
}
/**
* The resource mapper this loader is working with
* The object manager that initialized this loader. The object manager is responsible
* for supplying the mapper and object store used after HTTP transport is completed
*/
@property (nonatomic, readonly) RKObjectMapper* mapper;
/*
* In cases where CoreData is used for local object storage/caching, a reference to
* the managedObjectStore for use in retrieving locally cached objects using the store's
* managedObjectCache property.
*/
@property (nonatomic, retain) RKManagedObjectStore* managedObjectStore;
@property (nonatomic, readonly) RKObjectManager* objectManager;
/**
* The underlying response object for this loader
@@ -85,18 +81,15 @@
@property (nonatomic, copy) NSString* keyPath;
/**
* Return an auto-released loader with with an object mapper, a request, and a delegate
* Initialize and return an object loader for a resource path against an object manager. The resource path
* specifies the remote location to load data from, while the object manager is responsible for supplying
* mapping and persistence details.
*/
+ (id)loaderWithResourcePath:(NSString*)resourcePath mapper:(RKObjectMapper*)mapper delegate:(NSObject<RKObjectLoaderDelegate>*)delegate;
// TODO: Eliminate this method...
+ (id)loaderWithResourcePath:(NSString*)resourcePath client:(RKClient*)client mapper:(RKObjectMapper*)mapper delegate:(NSObject<RKObjectLoaderDelegate>*)delegate;
+ (id)loaderWithResourcePath:(NSString*)resourcePath objectManager:(RKObjectManager*)objectManager delegate:(NSObject<RKObjectLoaderDelegate>*)delegate;
/**
* Initialize a new object loader with an object mapper, a request, and a delegate
*/
- (id)initWithResourcePath:(NSString*)resourcePath mapper:(RKObjectMapper*)mapper delegate:(NSObject<RKObjectLoaderDelegate>*)delegate;
// TODO: Eliminate this method...
- (id)initWithResourcePath:(NSString*)resourcePath client:(RKClient*)client mapper:(RKObjectMapper*)mapper delegate:(NSObject<RKObjectLoaderDelegate>*)delegate;
- (id)initWithResourcePath:(NSString*)resourcePath objectManager:(RKObjectManager*)objectManager delegate:(NSObject<RKObjectLoaderDelegate>*)delegate;
@end

View File

@@ -14,47 +14,54 @@
#import "Errors.h"
#import "RKNotifications.h"
// Private Interfaces - Proxy access to RKObjectManager for convenience
@interface RKObjectLoader (Private)
@property (nonatomic, readonly) RKClient* client;
@property (nonatomic, readonly) RKObjectMapper* objectMapper;
@end
@implementation RKObjectLoader
@synthesize mapper = _mapper, response = _response, objectClass = _objectClass, keyPath = _keyPath;
@synthesize objectManager = _objectManager, response = _response, objectClass = _objectClass, keyPath = _keyPath;
@synthesize targetObject = _targetObject;
@synthesize managedObjectStore = _managedObjectStore;
+ (id)loaderWithResourcePath:(NSString*)resourcePath mapper:(RKObjectMapper*)mapper delegate:(NSObject<RKObjectLoaderDelegate>*)delegate {
return [self loaderWithResourcePath:resourcePath client:[RKClient sharedClient] mapper:mapper delegate:delegate];
+ (id)loaderWithResourcePath:(NSString*)resourcePath objectManager:(RKObjectManager*)objectManager delegate:(NSObject<RKObjectLoaderDelegate>*)delegate {
return [[[self alloc] initWithResourcePath:resourcePath objectManager:objectManager delegate:delegate] autorelease];
}
+ (id)loaderWithResourcePath:(NSString*)resourcePath client:(RKClient*)client mapper:(RKObjectMapper*)mapper delegate:(NSObject<RKObjectLoaderDelegate>*)delegate {
return [[[self alloc] initWithResourcePath:resourcePath client:client mapper:mapper delegate:delegate] autorelease];
}
- (id)initWithResourcePath:(NSString*)resourcePath mapper:(RKObjectMapper*)mapper delegate:(NSObject<RKObjectLoaderDelegate>*)delegate {
return [self initWithResourcePath:resourcePath client:[RKClient sharedClient] mapper:mapper delegate:delegate];
}
- (id)initWithResourcePath:(NSString*)resourcePath client:(RKClient*)client mapper:(RKObjectMapper*)mapper delegate:(NSObject<RKObjectLoaderDelegate>*)delegate {
if ((self = [self initWithURL:[client URLForResourcePath:resourcePath] delegate:delegate])) {
_mapper = [mapper retain];
_client = [client retain];
[_client setupRequest:self];
- (id)initWithResourcePath:(NSString*)resourcePath objectManager:(RKObjectManager*)objectManager delegate:(NSObject<RKObjectLoaderDelegate>*)delegate {
if ((self = [super initWithURL:[objectManager.client URLForResourcePath:resourcePath] delegate:delegate])) {
_objectManager = objectManager;
[self.objectManager.client setupRequest:self];
}
return self;
}
- (void)dealloc {
[_mapper release];
_mapper = nil;
// Weak reference
_objectManager = nil;
[_response release];
_response = nil;
[_keyPath release];
_keyPath = nil;
[_client release];
_client = nil;
self.managedObjectStore = nil;
_keyPath = nil;
[super dealloc];
}
#pragma mark - RKObjectManager Proxy Methods
- (RKClient*)client {
return self.objectManager.client;
}
- (RKObjectMapper*)objectMapper {
return self.objectManager.mapper;
}
#pragma mark Response Processing
@@ -95,17 +102,17 @@
// TODO: Unwind hard coding of JSON specific assumptions
if ([response isJSON]) {
error = [_mapper parseErrorFromString:[response bodyAsString]];
error = [self.objectMapper parseErrorFromString:[response bodyAsString]];
[(NSObject<RKObjectLoaderDelegate>*)_delegate objectLoader:self didFailWithError:error];
} else if ([response isServiceUnavailable] && [_client serviceUnavailableAlertEnabled]) {
} else if ([response isServiceUnavailable] && [self.client serviceUnavailableAlertEnabled]) {
// TODO: Break link with the client by using notifications
if ([_delegate respondsToSelector:@selector(objectLoaderDidLoadUnexpectedResponse:)]) {
[(NSObject<RKObjectLoaderDelegate>*)_delegate objectLoaderDidLoadUnexpectedResponse:self];
}
UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:[_client serviceUnavailableAlertTitle]
message:[_client serviceUnavailableAlertMessage]
UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:[self.client serviceUnavailableAlertTitle]
message:[self.client serviceUnavailableAlertMessage]
delegate:nil
cancelButtonTitle:NSLocalizedString(@"OK", nil)
otherButtonTitles:nil];
@@ -161,10 +168,10 @@
*/
NSArray* results = nil;
if (self.targetObject) {
[_mapper mapObject:self.targetObject fromString:[response bodyAsString]];
[self.objectMapper mapObject:self.targetObject fromString:[response bodyAsString]];
results = [NSArray arrayWithObject:self.targetObject];
} else {
id result = [_mapper mapFromString:[response bodyAsString] toClass:self.objectClass keyPath:_keyPath];
id result = [self.objectMapper mapFromString:[response bodyAsString] toClass:self.objectClass keyPath:_keyPath];
if ([result isKindOfClass:[NSArray class]]) {
results = (NSArray*)result;
} else {

View File

@@ -33,7 +33,8 @@ static RKObjectManager* sharedManager = nil;
}
- (id)initWithBaseURL:(NSString*)baseURL objectMapper:(RKObjectMapper*)mapper router:(NSObject<RKRouter>*)router {
if (self = [super init]) {
self = [super init];
if (self) {
_mapper = [mapper retain];
_router = [router retain];
_client = [[RKClient clientWithBaseURL:baseURL] retain];
@@ -140,10 +141,9 @@ static RKObjectManager* sharedManager = nil;
Class managedObjectLoaderClass = NSClassFromString(@"RKManagedObjectLoader");
if (managedObjectLoaderClass) {
objectLoader = [managedObjectLoaderClass loaderWithResourcePath:resourcePath client:self.client mapper:self.mapper delegate:delegate];
[(RKManagedObjectLoader*)objectLoader setManagedObjectStore:self.objectStore];
objectLoader = [managedObjectLoaderClass loaderWithResourcePath:resourcePath objectManager:self delegate:delegate];
} else {
objectLoader = [RKObjectLoader loaderWithResourcePath:resourcePath client:self.client mapper:self.mapper delegate:delegate];
objectLoader = [RKObjectLoader loaderWithResourcePath:resourcePath objectManager:self delegate:delegate];
}
return objectLoader;

View File

@@ -375,48 +375,6 @@ static const NSString* kRKModelMapperMappingFormatParserKey = @"RKMappingFormatP
@catch (NSException* e) {
NSLog(@"Caught exception:%@ when trying valueForKeyPath with path:%@ for elements:%@", e, elementKeyPath, elements);
}
// <<<<<<< HEAD
//
// if ([relationshipElements isKindOfClass:[NSArray class]] || [relationshipElements isKindOfClass:[NSSet class]]) {
// // NOTE: The last part of the keyPath contains the elementName for the mapped destination class of our children
// NSArray* componentsOfKeyPath = [elementKeyPath componentsSeparatedByString:@"."];
// Class class = [_elementToClassMappings objectForKey:[componentsOfKeyPath objectAtIndex:[componentsOfKeyPath count] - 1]];
// NSMutableSet* children = [NSMutableSet setWithCapacity:[relationshipElements count]];
// for (NSDictionary* childElements in relationshipElements) {
// id child = [self createOrUpdateInstanceOfModelClass:class fromElements:childElements];
// if (child) {
// [children addObject:child];
// }
// }
//
// [object setValue:children forKey:propertyName];
// } else if ([relationshipElements isKindOfClass:[NSDictionary class]]) {
// NSArray* componentsOfKeyPath = [elementKeyPath componentsSeparatedByString:@"."];
// Class class = [_elementToClassMappings objectForKey:[componentsOfKeyPath objectAtIndex:[componentsOfKeyPath count] - 1]];
// id child = [self createOrUpdateInstanceOfModelClass:class fromElements:relationshipElements];
// [object setValue:child forKey:propertyName];
// }
// }
//
// Class managedObjectClass = NSClassFromString(@"RKManagedObject");
// if (managedObjectClass && [object isKindOfClass:managedObjectClass]) {
// RKManagedObject* managedObject = (RKManagedObject*)object;
// NSDictionary* relationshipToPkPropertyMappings = [[managedObject class] relationshipToPrimaryKeyPropertyMappings];
// for (NSString* relationship in relationshipToPkPropertyMappings) {
// NSString* primaryKeyPropertyString = [relationshipToPkPropertyMappings objectForKey:relationship];
//
// NSNumber* objectPrimaryKeyValue = nil;
// @try {
// objectPrimaryKeyValue = [managedObject valueForKeyPath:primaryKeyPropertyString];
// } @catch (NSException* e) {
// NSLog(@"Caught exception:%@ when trying valueForKeyPath with path:%@ for object:%@", e, primaryKeyPropertyString, managedObject);
// }
//
// NSDictionary* relationshipsByName = [[managedObject entity] relationshipsByName];
// NSEntityDescription* relationshipDestinationEntity = [[relationshipsByName objectForKey:relationship] destinationEntity];
// id relationshipDestinationClass = objc_getClass([[relationshipDestinationEntity managedObjectClassName] cStringUsingEncoding:NSUTF8StringEncoding]);
// RKManagedObject* relationshipValue = [[[RKObjectManager sharedManager] objectStore] findOrCreateInstanceOfManagedObject:relationshipDestinationClass
// =======
// NOTE: The last part of the keyPath contains the elementName for the mapped destination class of our children
NSArray* componentsOfKeyPath = [elementKeyPath componentsSeparatedByString:@"."];