Fixes for memory leaks with RKParams related to HTTPBodyStream causing a retain

This commit is contained in:
Blake Watters
2011-06-20 13:41:42 -04:00
parent 8f91e85e04
commit 99ae37037a
9 changed files with 71 additions and 27 deletions

View File

@@ -271,6 +271,15 @@ NSString* RKPathAppendQueryParams(NSString* resourcePath, NSDictionary* queryPar
*/
+ (RKClient*)clientWithBaseURL:(NSString*)baseURL username:(NSString*)username password:(NSString*)password;
/**
* Return a client scoped to a particular base URL. If the singleton client is nil, the return client is set as the singleton
*
* @param baseURL The baseURL to set for the client. All requests will be relative to this base URL
* @see baseURL
* @return A configured RKClient instance ready to send requests
*/
- (id)initWithBaseURL:(NSString*)baseURL;
/////////////////////////////////////////////////////////////////////////
/// @name Constructing Resource Paths and URLs
/////////////////////////////////////////////////////////////////////////

View File

@@ -97,22 +97,7 @@ NSString* RKPathAppendQueryParams(NSString* resourcePath, NSDictionary* queryPar
}
+ (RKClient*)clientWithBaseURL:(NSString*)baseURL {
RKClient* client = [[[RKClient alloc] init] autorelease];
NSString* cacheDirForClient = [NSString stringWithFormat:@"RKClientRequestCache-%@",
[[NSURL URLWithString:baseURL] host]];
NSString* cachePath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0]
stringByAppendingPathComponent:cacheDirForClient];
client.cache = [[RKRequestCache alloc] initWithCachePath:cachePath
storagePolicy:RKRequestCacheStoragePolicyPermanently];
client.cachePolicy = RKRequestCachePolicyDefault;
client.baseURL = baseURL;
if (sharedClient == nil) {
[RKClient setSharedClient:client];
// Initialize Logging as soon as a client is created
RKLogInitialize();
}
RKClient* client = [[[self alloc] initWithBaseURL:baseURL] autorelease];
return client;
}
@@ -140,6 +125,29 @@ NSString* RKPathAppendQueryParams(NSString* resourcePath, NSDictionary* queryPar
return self;
}
- (id)initWithBaseURL:(NSString*)baseURL {
self = [self init];
if (self) {
NSString* cacheDirForClient = [NSString stringWithFormat:@"RKClientRequestCache-%@",
[[NSURL URLWithString:baseURL] host]];
NSString* cachePath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0]
stringByAppendingPathComponent:cacheDirForClient];
self.cache = [[RKRequestCache alloc] initWithCachePath:cachePath
storagePolicy:RKRequestCacheStoragePolicyPermanently];
self.cachePolicy = RKRequestCachePolicyDefault;
self.baseURL = baseURL;
if (sharedClient == nil) {
[RKClient setSharedClient:self];
// Initialize Logging as soon as a client is created
RKLogInitialize();
}
}
return self;
}
- (void)dealloc {
self.baseURL = nil;
self.username = nil;

View File

@@ -7,6 +7,11 @@
//
#import "RKParams.h"
#import "../Support/RKLog.h"
// Set Logging Component
#undef RKLogComponent
#define RKLogComponent lcl_cRestKitNetwork
/**
* The boundary used used for multi-part headers
@@ -183,10 +188,17 @@ NSString* const kRKStringBoundary = @"0xKhTmLbOuNdArY";
- (void)open {
_streamStatus = NSStreamStatusOpen;
RKLogTrace(@"RKParams stream opened...");
}
- (void)close {
_streamStatus = NSStreamStatusClosed;
RKLogTrace(@"RKParams stream closed. Releasing self.");
// NOTE: When we are assigned to the URL request, we get
// retained. We release ourselves here to ensure the retain
// count will hit zero after upload is complete.
[self release];
}
- (NSStreamStatus)streamStatus {

View File

@@ -47,7 +47,7 @@ extern NSString* const kRKStringBoundary;
[body appendData:[[NSString stringWithFormat:@"%@", value] dataUsingEncoding:NSUTF8StringEncoding]];
}
_bodyStream = [[NSInputStream inputStreamWithData:body] retain];
_bodyStream = [[NSInputStream alloc] initWithData:body];
_bodyLength = [body length];
}
@@ -56,7 +56,7 @@ extern NSString* const kRKStringBoundary;
- (id)initWithName:(NSString*)name data:(NSData*)data {
if ((self = [self initWithName:name])) {
_bodyStream = [[NSInputStream inputStreamWithData:data] retain];
_bodyStream = [[NSInputStream alloc] initWithData:data];
_bodyLength = [data length];
}
@@ -66,9 +66,9 @@ extern NSString* const kRKStringBoundary;
- (id)initWithName:(NSString*)name file:(NSString*)filePath {
if ((self = [self initWithName:name])) {
NSAssert1([[NSFileManager defaultManager] fileExistsAtPath:filePath], @"Expected file to exist at path: %@", filePath);
_fileName = [[filePath lastPathComponent] retain];
self.fileName = [[filePath lastPathComponent] retain];
_MIMEType = [[self mimeTypeForExtension:[filePath pathExtension]] retain];
_bodyStream = [[NSInputStream inputStreamWithFileAtPath:filePath] retain];
_bodyStream = [[NSInputStream alloc] initWithFileAtPath:filePath];
NSError* error;
NSDictionary* attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:&error];

View File

@@ -115,7 +115,7 @@
[_URLRequest release];
_URLRequest = nil;
[_params release];
_params = nil;
_params = nil;
[_additionalHTTPHeaders release];
_additionalHTTPHeaders = nil;
[_username release];
@@ -135,6 +135,8 @@
if (_params && (_method != RKRequestMethodGET && _method != RKRequestMethodHEAD)) {
// Prefer the use of a stream over a raw body
if ([_params respondsToSelector:@selector(HTTPBodyStream)]) {
// NOTE: This causes the stream to be retained. For RKParams, this will
// cause a leak unless the stream is released. See [RKParams close]
[_URLRequest setHTTPBodyStream:[_params HTTPBodyStream]];
} else {
[_URLRequest setHTTPBody:[_params HTTPBody]];