views:

59

answers:

2

Hello - In my app, I have a bunch of different image packs to download. The images are downloaded from my website one by one. The packs contain anywhere from 100-1500 images and each image is about 100KB-200KB.

When downloading the images, I have a method that selects the images to download, then I have a second method that does the actual downloading based on parameters sent from the main method. Here is the code for the download method:

-(BOOL) downloadImageName:(NSString *)imageName ImageGroup:(NSString *)imageGroup AndRow:(int)row {

    NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
                                                     NSUserDomainMask, YES);
    NSString *docsPath = [paths objectAtIndex:0];

    NSURL *downloadURL = [NSURL URLWithString:[NSString stringWithFormat:@"http://www.website.com/%@_0001.jpg",imageName]];
    NSData *data = [NSData dataWithContentsOfURL:downloadURL];
    NSString *savePath = [NSString stringWithFormat:@"%@/%@^%@_%@.jpg",docsPath,currentServerCycle,imageGroup,imageName];
    BOOL downloaded = [data writeToFile:savePath atomically:YES];

    if (downloaded) 
             return YES; 
    }

    else {
    return NO;
    }
}

The problem I am having is this:

When I run this with performance tools looking at allocations I'm seeing that the app is keeping mallocs (NSConcreteData) each time an image is downloaded and only releasing them when the main method (the one calling this download method) completes. Thats fine for the smaller image packs, but the larger ones are obviously crashing after my total allocations hit something like 300+MB (the normal amount of allocations in my app is about 3mb).

They arent leaking, because once the image pack is downloaded and the method ends, all the mallocs are gone.

I have tried manually allocing and releasing the NSData *data but it has no effect.

+1  A: 

Perhaps the autorelease pool the objects are in is not being drained until the main method returns. You might try adding NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; at the beginning of your download method, then [pool drain]; right before you return from the download method. You need to make sure you release the pool before you return no matter where you return otherwise you'll leak the pool.

Also, just as a point of standard Objective-C style, your method should be named:

-(BOOL) downloadImageName:(NSString *)imageName imageGroup:(NSString *)imageGroup andRow:(int)row

with lowercase letters to start the "imageGroup:" and "andRow:" argument names.

Andrew Madsen
That got it thanks! I had never used an autorelease pool on a method that I didn't plan on using in a separate thread before. And thanks for pointing out the naming error.
Brodie
A: 

Have you found a solution? I have the same problem but in my case the images (mallocs NSConcreteData) never get released. This is not NSAutoreleasePool problem, it release CFDATA(Store) when a chapter of images ends.

Here is the code

NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:[self link]] options:(NSUInteger) nil error:nil];
[Utils hideNetworkActivity];
if (data == nil) {

    return FALSE;
}

ComicImage *comicImg = [NSEntityDescription 
                        insertNewObjectForEntityForName:@"ComicImage" 
                        inManagedObjectContext:context];

[comicImg setImageData:data];
[comicImg setPage:self];


[self setImage:comicImg];
[self setHasImage:[NSNumber numberWithBool:TRUE]];
[Utils saveDatabaseWithContext:[Utils databaseContext]];        

return TRUE;

`

All this is a function in a while with the pool and a queue, but like i have said just release the CFDATA

The problem is here: NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:[self link]] options:(NSUInteger) nil error:nil];

I've tried: NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:[self link]]], with alloc and initWithContentsOfURL, without cache... but the images remain and make the app eventually crashes.

Any idea?

anti
Welcome to Stack Overflow, Anti. SO isn't a forum-- please post your issue as a new question.
quixoto