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];
        }
Was it helpful?

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top