NSJSONSerialization leaks in Callback Block
Question
I'm trying to use Blocks as callbacks for an API request via the method below. This method takes a Block that is nested in this method's Block. It works... BUT,
If an Object that has called this method is dealloced, NSJSONSerialization dumps out a massive memory leak. It's all good while everything is running. The leak only happens after the requesting object is gone. The leaks are nearly all NSPlaceHolder types.
I'm at my wits end and any ideas are greatly appreciated!
- (void)sendRequestUsingNSURLConnectionWith:(NSURLRequest *)request andCallback:(void (^)(id))handler
{
__block __typeof__(self)blockSelf = self;
// CL: build a block to be run asynchronously
ApiClientCallback handleResponse = [[^(NSURLResponse *response, NSData *data, NSError *error) {
id results = nil;
// CL: http errors would be caught here.
if (error) {
NSLog(@"[%@ %@] HTTP error: %@", NSStringFromClass([blockSelf class]), NSStringFromSelector(_cmd), error.localizedDescription);
results = error;
}
else {
// CL: parse the JSON
NSError *jsonError = nil;
NSError *apiError = nil;
if (data) {
results = [NSJSONSerialization JSONObjectWithData:data
options:NSJSONReadingMutableContainers
error:&jsonError];
}
else {
results = nil;
}
// CL: json errors would be caught here.
if (jsonError) {
NSLog(@"[%@ %@] JSON error: %@", NSStringFromClass([blockSelf class]), NSStringFromSelector(_cmd), error.localizedDescription);
results = error;
}
// CL: Check for API errors.
else if ([blockSelf checkApiErrorCode:results error:&apiError]) {
//CL: if there's an error make the NSError object the result.
if (apiError) results = apiError;
}
}
// CL: Send result to the completion block of the requesting object
handler(results);
} copy] autorelease];
[NSURLConnection sendAsynchronousRequest:request
queue:self.opQueue
completionHandler:handleResponse];
}
Solution
Per request I'm documenting the conclusion here. It turned out that I had forgotten to call super dealloc in the dealloc method of a sub class. This caused the super to leak all of it's retained properties upon deallocation. Programmer error. Note that this scenario was happening pre ARC.