iPhone - Memory Leak - Nsdata Datawithcontentsofurl & UIwebview

memory leak problem using NSData in iPhone

I had issues with this as well in my Large project. After working with an Apple engineer on trying to locate the leaks, he finally asked the main Apple dev team behind NSURLConnection. They basically said that there is an internal cache that is not clearable at all in NSURLConnection and it was a known issue.

So I set out looking for alternatives. I found ASIHTTPConnection (link below) which works off of CFNetwork. It is designed to be a drop-in replacement for NSURLConnection, plus a bunch of other awesome goodies like downloading to disk instead of memory, download resuming, progress bar callbacks etc..

I have used it in all my projects and have never had any issues or complaints. An, in answer to your question, this is how I got rid of those memory leaks.

http://allseeing-i.com/ASIHTTPRequest/

Memory leak using dataWithContentsOfURL in a loop

The first thing I'd suggest is using an @autoreleasepool to control the peak amount of memory consumed. Right now, you're downloading the contents into the NSData as an autorelease object, and when done, you're nil-ing that variable, which simple flags it to be deallocated once the autorelease pool is drained (which will not happen until loadImagesFromList is done). By (a) moving the variable declarations inside the for loop; and (b) wrapping this in an @autoreleasepool, your memory will be deallocated as the individual downloads finish.

-(void)loadImagesFromList:(NSArray *)theArray
sourceBundle:(NSString *)bundlePath
destBundle:(NSString *)localBundlePath
manager:(NSFileManager *)manager {

// initialize the progress and activity indicator
dispatch_async(dispatch_get_main_queue(), ^{
// your UI update here
});

int counter = 0;
float prog = 0;
float increment = 1.0 / [theArray count];
float stepSize = [theArray count] / 10;

for (NSString *file in theArray)
{
@autoreleasepool {
if (stopFlag) {
NSLog(@"I see stopFlag = true, counter = %d, prog = %f", counter, prog);
return;
}

NSString *srcFile = [bundlePath stringByAppendingPathComponent:file];
NSString *destFile = [localBundlePath stringByAppendingPathComponent:file];

counter += 1;
prog += increment;
if (counter == stepSize) {
dispatch_async(dispatch_get_main_queue(), ^{
self.progressIndictor.progress = prog;
});
counter = 0;
}

// only download if file isn't already here
BOOL fileExists = [manager fileExistsAtPath:destFile]; // check if we already have it
if (!fileExists) {
NSError *error = nil;

// jpg or folder check
if ([[destFile pathExtension] isEqualToString:@"jpg"]) {
NSURL *url = [NSURL URLWithString:srcFile];
NSData *data = [NSData dataWithContentsOfURL:url
options:0
error:&error];

[data writeToFile:destFile options:NSDataWritingAtomic error:&error];
} else {
[manager createDirectoryAtPath:destFile withIntermediateDirectories:YES attributes:nil error:&error];
}
}
}
}
}

Export UIWebView Full Content to NSData? iPhone

Probably late enough to respond to this, but I figured out you can get all the data from the request you made with NSCachedURLResponse as such:

NSCachedURLResponse* response = [[NSURLCache sharedURLCache] 
cachedResponseForRequest:[webView request]];
NSData* data = [response data];

Memory leak while using performSelectorInBackground

I think you should use

[pool release];

rather than

[pool drain];

which is far more better practice.

Also can you try to release activityIndicator in the main thread?

From the code you have given I can't find any other cause for leak.. Have you tried to run your code using leak instrument and static analyzer?



Related Topics



Leave a reply



Submit