Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSURLConnection Memory Leak

I run the instruments tool and get some Memory Leaks and i don´t know how to handle this. I´m using ARC!

This is my Code:

+ (MARequest *)requestImageThumb:(NSString *)imageName
                      object:(NSInteger)objectId {
   NSString* urlString = [NSString stringWithFormat:@"%@/%@", kBaseImageThumbURL, imageName];

   LogTrace(@"Creating image thumb request for file %@", imageName);

   //Here starts the leak!!
   return [MARequest createWithURL:[NSURL URLWithString:urlString]
                           type:REQUEST_TYPE_GET_IMAGE];
}


+ (MARequest *)createWithURL:(NSURL *)url
                    type:(NSInteger)type {

   MARequest* r = [[MARequest alloc] init];

   r.url = url;
   r.requestType = type;
   r.responseData = [[NSMutableData alloc] init];
   r.connection = [[NSURLConnection alloc] initWithRequest:[NSURLRequest requestWithURL:r.url]
                                               delegate:r
                                       startImmediately:NO];

   return r;
}

And here my NSURLConnectionDelegate

#pragma mark - NSURLConnectionDelegate
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
   LogTrace(@"request %@: didReceiveResponse", self.url);
   [self.responseData setLength:0];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
   LogTrace(@"request %@: didReceiveData, %d bytes", self.url, data.length);

   [self.responseData appendData:data];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
   LogTrace(@"request %@: didFailWithError: %@", self.url, [error description]);

   self.connection = nil;
   self.failed = YES;

[self invokeAction];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
   LogTrace(@"request %@: connectionDidFinishLoading, %d bytes", self.url, [self.responseData length]);
   self.connection = nil;

   [self invokeAction];
}

EDIT:

I changed my Code to this now, but sadly it still gives me a Memory Leak....

+ (MARequest *)requestImageThumb:(NSString *)imageName
                      object:(NSInteger)objectId {
    NSString* urlString = [NSString stringWithFormat:@"%@/%@", kBaseImageThumbURL, imageName];

    LogTrace(@"Creating image thumb request for file %@", imageName);

    return [MARequest requestWithURL:[NSURL URLWithString:urlString]
                           type:REQUEST_TYPE_GET_IMAGE];
}

+ (MARequest *)requestWithURL:(NSURL *)url
                    type:(NSInteger)type {

   MARequest* r = [[MARequest alloc] init];

   r.url = url;
   r.requestType = type;
   r.responseData = [[NSMutableData alloc] init];
   r.connection = [[NSURLConnection alloc] initWithRequest:[NSURLRequest requestWithURL:r.url]
                                               delegate:r
                                       startImmediately:NO];



   return r;
}
like image 486
Davis Avatar asked Dec 02 '25 02:12

Davis


1 Answers

EDIT: after your changes, the explanation for the leak is the following:

You have a circular dependency between your GFRequest object and the NSURLConnection object, thus preventing both from being correctly deallocated. Indeed, you are setting the GFRequest's connection property to a NSURLConnection instance:

   r.connection = [[NSURLConnection alloc] initWithRequest:[NSURLRequest requestWithURL:r.url]

while at the same time also making the r be the delegate of that NSURLConnection:

             delegate:r

What happens is that NSURLConnection's delegate does a retain on its delegate, and this is causing the dependency cycle.

I do not see an easy way to break the dependency, though, and keep your current design.

You could simply avoid storing your connection inside of the request, or you could not use the request as a delegate for the connection. Possibly, you should consider the possibility of subclassing NSURLConnection and have it act as a delegate to itself.

OLD ANSWER:

There is a mismatch between the outer method name and the inner one:

+ (MARequest *)requestImageThumb:(NSString *)imageName
…
   return [MARequest createWithURL:[NSURL URLWithString:urlString]

For the static analyser those have different semantics as to object ownership.

Replace the first one with:

+ (MARequest *)createRequestImageThumb:(NSString *)imageName

or the second one with:

   return [MARequest requestWithURL:[NSURL URLWithString:urlString]

Depending on which semantics is proper for you case.

like image 87
sergio Avatar answered Dec 03 '25 19:12

sergio



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!