3

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];
        }
GnarlyDog
  • 1,247
  • 1
  • 17
  • 24
  • 1
    Please explain "NSJSONSerialization dumps out a massive memory leak" – hooleyhoop Jan 08 '12 at 12:27
  • I've found the issue and I'm utterly embarrassed at what the cause was. The requesting object that was causing the leak was a subclass of another object. I realized that I actually forgot to include [super dealloc] in the subclass. The subclass has just a couple properties being filled by the request while the super has about 15. For testing I was running the request many times before dealloc, thus the large leak. Doh! – GnarlyDog Jan 08 '12 at 19:22
  • 1
    You should get a warning if you miss a [super dealloc] if you don't you might want to check your build settings – hooleyhoop Jan 08 '12 at 19:58
  • Good point! In fact, in addition to no warnings, the static analyzer didn't gripe either. I haven't checked into it yet but a) shouldn't the static analyzer catch such a scenario? and b) can one customize the static analyzer as well? – GnarlyDog Jan 08 '12 at 20:24
  • If this is a solved problem, please post the answer below and accept it so this no longer appears as an unanswered question. Thanks! – bneely Feb 18 '14 at 18:25

1 Answers1

0

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.

GnarlyDog
  • 1,247
  • 1
  • 17
  • 24