Allocations using AFNetworking request

346 views Asked by At

I'm using AFNetworking to send requests but when the request finishes its job I'm getting this memory allocations in instruments and they stay there forever... If I try to start another request the application receives memory warning several times and thus it's forced to close.

Graph    Category   Live Bytes  # Living    # Transitory    Overall Bytes   # Overall   # Allocations (Net / Overall)
1   CFString (store)    4,86 MB 29  3595    30,78 MB    3624    <XRRatioObject: 0x7ffd1c5dc3f0>  %0.00, %0.17
1   Malloc 3,91 MB  3,91 MB 1   1   7,83 MB 2   <XRRatioObject: 0x7ffd1c5dc3f0>  %0.00, %0.00

And the inner allocations for each one:

First

#   Address Category    Timestamp   Live    Size    Responsible Library Responsible Caller
0   0x4d28000   CFString (store)    01:12.165.450   •   4923392 CFNetwork   _ZL19_cacheKeyForRequestPK13_CFURLRequest
1   0x36b8000   CFString (store)    00:54.705.461   •   172032  CFNetwork   _ZL19_cacheKeyForRequestPK13_CFURLRequest
2   0x1e3f5a00  CFString (store)    01:12.326.108   •   1024    CFNetwork   _ZL19_cacheKeyForRequestPK13_CFURLRequest

Second

#   Address Category    Timestamp   Live    Size    Responsible Library Responsible Caller
0   0x6903000   Malloc 3,91 MB  01:01.583.198   •   4104192 Foundation  -[NSConcreteMutableData initWithLength:]

Edit 1

Here is the code we are using to create the requests:

// Do a json request
+ (void) doJsonRequestWithPath
: (NSString *) path
withMethod: (NSString *) method
withParameters: (id) parameters
withHeaders: (NSDictionary *) headers
onSuccess: (void(^)(NSURLRequest *, NSHTTPURLResponse *, id))success
onFailure: (void(^)(NSURLRequest *, NSHTTPURLResponse *, NSError *, id))failure
{    
    // Register json request operation
    [httpClient registerHTTPOperationClass:[AFJSONRequestOperation class]];
    // Json parameter encoding
    [httpClient setParameterEncoding:AFJSONParameterEncoding];

    NSMutableURLRequest *request;


    if ([parameters isKindOfClass:[NSDictionary class]]) {
        // Create a request with the http client + path and params
        request = [httpClient requestWithMethod:method path:path parameters:parameters];
    }
    else {
        request = [httpClient requestWithMethod:method path:path parameters:nil];
        [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
        //[request setValue:@"100-continue" forHTTPHeaderField:@"Expect"];
        [request setHTTPBody:[parameters dataUsingEncoding:NSUTF8StringEncoding]];
    }

    [request setCachePolicy:NSURLRequestReloadIgnoringCacheData];
    [request setTimeoutInterval:20];

    // Add headers to the request if there is any
    if (headers != nil)
        [self addHeadersToRequest:request fromDictionary:headers];

    // Create a json request operation
    AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:success failure:failure];



    // Starts the operation
    [operation start];
}

Edit 2

We have a recursive call

- (void)sendFingerprintAtIndex:(NSInteger) index withGuid:(NSString *) guid
{
    SendActivationRequest *sendActivationRequest = [[SendActivationRequest alloc]
                                                    initWithGuid: guid
                                                    andWithTotalImages:4
                                                    andWithImageIndex:index
                                                    andImageType:2 //digital
                                                    andWithImage:image];

[self.activationDao sendActivationRequest:sendActivationRequest withCompletionBlock:^(NSString *hash, NSArray *errors) {        
        if (hash) {

                .
                .
                .
            }
            else {
                // recursive call
                [self sendFingerprintAtIndex:newIndex withGuid:guid];
            }
        }
        else
        {
            self.completionBlockController(NO, [errors objectAtIndex:0]);
        }
    }];
}

And in the Dao

- (void) sendActivationRequest:(SendActivationRequest *) sendActivationRequest withCompletionBlock:(void (^)(NSString *, NSArray *))completionBlock
{
    // Path
    NSString *path = @"EnviarAtivacao";

    id params = [sendActivationRequest getParams];
    NSDictionary *headers = [sendActivationRequest getHeader];

        // Do a json post request
    [self doJsonPostRequestWithPath:path
                     withParameters:params
                        withHeaders:headers
                          onSuccess:^(NSURLRequest *request, NSHTTPURLResponse *response, id json) {
                              .
                              .
                              .                  

                          } onFailure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *err, id json) {
                              .
                              .
                              .


                          }];

}

Thanks!

2

There are 2 answers

1
mattt On BEST ANSWER

Those are allocations from the app's shared NSURLCache instance.

If I try to start another request the application receives memory warning several times and thus it's forced to close.

NSURLCache should automatically discard its in-memory cache when a memory warning is issued. I'm not sure what you mean by "it's forced to close", but this may well be an issue of you freeing unused memory in your view controllers when a memory warning fires.

4
JonahGabriel On

You have retain cycles in your completion blocks. You should not reference "self" in any blocks. Try doing something like this

__weak MyClass *wSelf = self;
MyCompletionBlock completionBlock = ^{
    __strong MyClass *sSelf = wSelf;
   [sSelf doThings];
}