I have several memory leaks(NO! see Update 1) in my App and they all come down to an asynchronous URLRequest. The code below gives me a memory leak, it seems like the 'data' is never released (The code below is logically not used in my app as it is a completely useless infinite loop, I just wrote it to show the memory leak. This makes the used RAM go from 5 to 20 MB in less than one second. My internet speed does match this [just for the record]):
- (void)start{
NSOperationQueue *oQC = [[NSOperationQueue alloc] init];
NSLog(@"a");
[NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.online-image-editor.com//styles/2014/images/example_image.png"]] queue:oQC completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
NSLog(@"b");
[self start];
}];
}
I have also tried setting data = nil, but that did, like supposed, not work. Does anybody have any Idea of how to avoid the memory leak and if this is the normal behavior of a NSURLConnection?
UPDATE 1:
This doesn't seem to be related to a memory leak but to a caching problem. (Thanks to @rdelmar, who saw the problem, but his solution doesn't quite work)
Based on this post I have tried creating a new 'Loader' class with this in it's .h file:
#import <Foundation/Foundation.h>
@interface Loader : NSObject <NSURLConnectionDelegate, NSURLConnectionDataDelegate>
@property NSMutableData *mData;
@property (nonatomic, copy) void (^returnBlock)(NSData *data, NSError *error);
- (id)initForWhateverWithURLString:(NSString*)urlString andHandler:(void (^)(NSData *data, NSError *error))handler;
@end
And this in it's .m file:
#import "Loader.h"
@implementation Loader
@synthesize mData;
- (id)initForWhateverWithURLString:(NSString*)urlString andHandler:(void (^)(NSData *data, NSError *error))handler{
self = [super init];
if (self) {
/*NSOperationQueue *oQC = [NSOperationQueue mainQueue];
[NSURLConnection sendAsynchronousRequest:mUR queue:oQC completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
[[NSURLCache sharedURLCache] removeCachedResponseForRequest:mUR];
handler(nil, nil);
}];*/
mData = [NSMutableData new];
self.returnBlock = handler;
NSMutableURLRequest *mUR = [[NSURLRequest requestWithURL:[NSURL URLWithString:urlString] cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60] mutableCopy];
NSURLConnection *URLCon = [[NSURLConnection alloc] initWithRequest:mUR delegate:self];
[URLCon start];
}
return self;
}
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse{
return nil;
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
[mData appendData:data];
data = nil;
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection{
self.returnBlock(mData, nil);
mData = nil;
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
self.returnBlock(nil, error);
}
@end
I also implemented:
NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:0 diskCapacity:0 diskPath:@"nsurlcache"];
[NSURLCache setSharedURLCache:sharedCache];
Still, neither of these methods helps reducing the drastic RAM usage!