Fixed a number of memory leaks. Added ability to cancel requests. Optimized the property inspector with cacheing. Much improved performance!

This commit is contained in:
Blake Watters
2010-03-11 12:19:18 -05:00
parent db87576d79
commit 3c5fda2dee
12 changed files with 70 additions and 16 deletions

View File

@@ -153,25 +153,25 @@ static RKClient* sharedClient = nil;
- (RKResponse*)getSynchronously:(NSString*)resourcePath params:(NSDictionary*)params {
NSString* resourcePathWithQueryString = [NSString stringWithFormat:@"%@?%@", resourcePath, [params URLEncodedString]];
RKRequest* request = [[RKRequest alloc] initWithURL:[self URLForResourcePath:resourcePathWithQueryString]];
RKRequest* request = [[[RKRequest alloc] initWithURL:[self URLForResourcePath:resourcePathWithQueryString]] autorelease];
[self setupRequest:request];
return [request getSynchronously];
}
- (RKResponse*)postSynchronously:(NSString*)resourcePath params:(NSObject<RKRequestSerializable>*)params {
RKRequest* request = [[RKRequest alloc] initWithURL:[self URLForResourcePath:resourcePath]];
RKRequest* request = [[[RKRequest alloc] initWithURL:[self URLForResourcePath:resourcePath]] autorelease];
[self setupRequest:request];
return [request postParamsSynchronously:params];
}
- (RKResponse*)putSynchronously:(NSString*)resourcePath params:(NSObject<RKRequestSerializable>*)params {
RKRequest* request = [[RKRequest alloc] initWithURL:[self URLForResourcePath:resourcePath]];
RKRequest* request = [[[RKRequest alloc] initWithURL:[self URLForResourcePath:resourcePath]] autorelease];
[self setupRequest:request];
return [request putParamsSynchronously:params];
}
- (RKResponse*)deleteSynchronously:(NSString*)resourcePath {
RKRequest* request = [[RKRequest alloc] initWithURL:[self URLForResourcePath:resourcePath]];
RKRequest* request = [[[RKRequest alloc] initWithURL:[self URLForResourcePath:resourcePath]] autorelease];
[self setupRequest:request];
return [request deleteSynchronously];
}

View File

@@ -159,6 +159,7 @@
return [[self elementToPropertyMappings] allValues];
}
// TODO: I get eliminated...
+ (NSString*)formatElementName:(NSString*)elementName forMappingFormat:(RKMappingFormat)format {
if (RKMappingFormatXML == format) {
return [[elementName camelize] dasherize];
@@ -192,6 +193,7 @@
// TODO: This implementation is Rails specific. Consider using an adapter approach.
// TODO: Gets handled in a Rails adapter, moved completely off the model itself...
// TODO: Moves to the model mapper? encodeProperties:?
- (NSDictionary*)resourceParams {
NSDictionary* elementsAndProperties = [self elementNamesAndPropertyValues];
NSMutableDictionary* resourceParams = [NSMutableDictionary dictionaryWithCapacity:[elementsAndProperties count]];

View File

@@ -13,6 +13,10 @@
@synthesize mapper = _mapper, delegate = _delegate, callback = _callback;
+ (id)loaderWithMapper:(RKModelMapper*)mapper {
return [[[self alloc] initWithMapper:mapper] autorelease];
}
- (id)initWithMapper:(RKModelMapper*)mapper {
if (self = [self init]) {
_mapper = [mapper retain];
@@ -21,6 +25,11 @@
return self;
}
- (void)dealloc {
[_mapper release];
[super dealloc];
}
- (SEL)memberCallback {
return @selector(loadModelFromResponse:);
}
@@ -72,9 +81,9 @@
- (void)processLoadModelsInBackground:(RKResponse *)response {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSLog(@"RKModelLoader -> processLoadModelsInBackground: Processing response %@", [response payloadString]);
// NSLog(@"RKModelLoader -> processLoadModelsInBackground: Processing response %@", [response payloadString]);
NSArray* models = [_mapper mapFromString:[response payloadString]];
NSLog(@"RKModelLoader -> processLoadModelsInBackground: Loaded models %@", models);
// NSLog(@"RKModelLoader -> processLoadModelsInBackground: Loaded models %@", models);
[_delegate performSelectorOnMainThread:self.callback withObject:models waitUntilDone:NO];
[pool release];
}

View File

@@ -99,7 +99,7 @@ static RKModelManager* sharedManager = nil;
if ([self isOffline]) {
return nil;
}
RKModelLoader* loader = [[RKModelLoader alloc] initWithMapper:self.mapper];
RKModelLoader* loader = [RKModelLoader loaderWithMapper:self.mapper];
loader.delegate = delegate;
loader.callback = callback;
@@ -113,7 +113,7 @@ static RKModelManager* sharedManager = nil;
if ([self isOffline]) {
return nil;
}
RKModelLoader* loader = [[RKModelLoader alloc] initWithMapper:self.mapper];
RKModelLoader* loader = [RKModelLoader loaderWithMapper:self.mapper];
loader.delegate = delegate;
loader.callback = callback;
@@ -124,7 +124,7 @@ static RKModelManager* sharedManager = nil;
if ([self isOffline]) {
return nil;
}
RKModelLoader* loader = [[RKModelLoader alloc] initWithMapper:self.mapper];
RKModelLoader* loader = [RKModelLoader loaderWithMapper:self.mapper];
loader.delegate = delegate;
loader.callback = callback;
@@ -135,7 +135,7 @@ static RKModelManager* sharedManager = nil;
if ([self isOffline]) {
return nil;
}
RKModelLoader* loader = [[RKModelLoader alloc] initWithMapper:self.mapper];
RKModelLoader* loader = [RKModelLoader loaderWithMapper:self.mapper];
loader.delegate = delegate;
loader.callback = callback;
@@ -148,7 +148,7 @@ static RKModelManager* sharedManager = nil;
if ([self isOffline]) {
return nil;
}
RKModelLoader* loader = [[RKModelLoader alloc] initWithMapper:self.mapper];
RKModelLoader* loader = [RKModelLoader loaderWithMapper:self.mapper];
loader.delegate = delegate;
loader.callback = callback;
@@ -162,7 +162,7 @@ static RKModelManager* sharedManager = nil;
if ([self isOffline]) {
return nil;
}
RKModelLoader* loader = [[RKModelLoader alloc] initWithMapper:self.mapper];
RKModelLoader* loader = [RKModelLoader loaderWithMapper:self.mapper];
loader.delegate = delegate;
loader.callback = callback;

View File

@@ -10,7 +10,7 @@
@interface RKObjectPropertyInspector : NSObject {
NSMutableDictionary* _cachedPropertyNamesAndTypes;
}
/**

View File

@@ -12,6 +12,19 @@
@implementation RKObjectPropertyInspector
- (id)init {
if (self = [super init]) {
_cachedPropertyNamesAndTypes = [[NSMutableDictionary alloc] init];
}
return self;
}
- (void)dealloc {
[_cachedPropertyNamesAndTypes release];
[super dealloc];
}
- (NSString*)propertyTypeFromAttributeString:(NSString*)attributeString {
NSString *type = [NSString string];
NSScanner *typeScanner = [NSScanner scannerWithString:attributeString];
@@ -28,7 +41,11 @@
}
- (NSDictionary *)propertyNamesAndTypesForClass:(Class)class {
NSMutableDictionary *propertyNames = [NSMutableDictionary dictionary];
NSMutableDictionary* propertyNames = [_cachedPropertyNamesAndTypes objectForKey:class];
if (propertyNames) {
return propertyNames;
}
propertyNames = [NSMutableDictionary dictionary];
//include superclass properties
Class currentClass = class;
@@ -61,6 +78,8 @@
free(propList);
currentClass = [currentClass superclass];
}
[_cachedPropertyNamesAndTypes setObject:propertyNames forKey:class];
return propertyNames;
}

View File

@@ -27,6 +27,7 @@
if (self = [self init]) {
_URL = [URL retain];
_URLRequest = [[NSMutableURLRequest alloc] initWithURL:_URL];
_connection = nil;
}
return self;
@@ -49,6 +50,7 @@
[_additionalHTTPHeaders release];
[_username release];
[_password release];
[self cancel];
[super dealloc];
}
@@ -75,7 +77,7 @@
NSDictionary* userInfo = [NSDictionary dictionaryWithObjectsAndKeys:[self HTTPMethod], @"HTTPMethod", [self URL], @"URL", sentAt, @"sentAt", nil];
[[NSNotificationCenter defaultCenter] postNotificationName:kRKRequestSentNotification object:self userInfo:userInfo];
RKResponse* response = [[[RKResponse alloc] initWithRestRequest:self] autorelease];
[[NSURLConnection connectionWithRequest:_URLRequest delegate:response] retain];
_connection = [[NSURLConnection connectionWithRequest:_URLRequest delegate:response] retain];
}
- (RKResponse*)sendSynchronous {
@@ -147,4 +149,11 @@
return [self sendSynchronous];
}
- (void)cancel {
[_connection cancel];
[_connection release];
_connection = nil;
}
@end

View File

@@ -83,7 +83,6 @@
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[connection release];
NSDate* receivedAt = [NSDate date]; // TODO - Carry around this timestamp on the response or request?
NSDictionary* userInfo = [NSDictionary dictionaryWithObjectsAndKeys:[_request HTTPMethod], @"HTTPMethod", [_request URL], @"URL", receivedAt, @"receivedAt", nil];
[[NSNotificationCenter defaultCenter] postNotificationName:kRKResponseReceivedNotification object:self userInfo:userInfo];

View File

@@ -58,8 +58,10 @@
*/
+ (NSFetchRequest*)request;
// TODO: objectsWithRequest
+ (NSArray*)collectionWithRequest:(NSFetchRequest*)request;
+ (id)objectWithRequest:(NSFetchRequest*)request;
// TODO: objectsWithPredicate
+ (NSArray*)collectionWithPredicate:(NSPredicate*)predicate;
+ (id)objectWithPredicate:(NSPredicate*)predicate;
+ (NSArray*)allObjects;
@@ -113,6 +115,7 @@
// The server side name of the model?
// TODO: Should be registered on the model manager somehow...
// TODO: Use entity name on managed model?
+ (NSString*)modelName;
/**
@@ -127,11 +130,13 @@
// Instance Methods
// saves the managed object context
// TODO: Gets moved off
- (NSError*)save;
/**
* Deletes the object from the managed object context
*/
// TODO: Gets moved off
- (void)destroy;
@end

View File

@@ -12,6 +12,8 @@
@protocol RKModelLoaderDelegate <RKRequestDelegate>
// TODO: didLoadModel: modelDidLoad: modelLoaderDidLoad:
/**
* Invoked when a request sent through the model manager encounters an error. The model will be nil if the request was
* not dispatched with a model object instance
@@ -59,6 +61,7 @@
*/
@property (nonatomic, readonly) SEL collectionCallback;
+ (id)loaderWithMapper:(RKModelMapper*)mapper;
/**
* Initialize a new model loader with a model mapper

View File

@@ -42,6 +42,8 @@ typedef enum {
*/
+ (NSDictionary*)elementToRelationshipMappings;
// TODO: Add an errors property. This will be populated when there are errors in the mapping.
@optional
/**

View File

@@ -15,6 +15,7 @@
@interface RKRequest : NSObject {
NSURL* _URL;
NSMutableURLRequest* _URLRequest;
NSURLConnection* _connection;
NSDictionary* _additionalHTTPHeaders;
NSObject<RKRequestSerializable>* _params;
id _delegate;
@@ -130,6 +131,11 @@
*/
- (RKResponse*)deleteSynchronously;
/**
* Cancels the underlying URL connection
*/
- (void)cancel;
@end
/**