views:

95

answers:

1
+2  Q: 

Load 100 UIImages

I am busy with an iPhone application. A part of it I load 100 small images from Flickr as an UIButton. The problem is how to handle the memory. it loads around 5-6 mb each time. When I dealloc the view trough navigationController popViewController the memory stays almost the same.

What I do now is loop all the images and put the request to an ASINetworkQueue. When the loop is ready I do [networkQueue go].

//Loop images
for (NSDictionary* message in output)
{
    NSString *imageURL = [[NSString alloc] initWithFormat:@"http://farm%@.static.flickr.com/%@/%@_%@_s.jpg", [message objectForKey:@"farm"], [message objectForKey:@"server"], [message objectForKey:@"id"], [message objectForKey:@"secret"]];

    if(cx > 280) { cy = cy + 78; cx = 6.0f; }

    //user data for the request
    NSMutableDictionary *imageInfo = [[NSMutableDictionary alloc] init];

    //init Image
    CGRect myImageRect = CGRectMake(cx, cy, 72.0f, 72.0f);
    UIButton *myImage = [[UIButton alloc] initWithFrame:myImageRect];
    [myImage setTag:i];

    [myImage setBackgroundColor:[UIColor whiteColor]]; //grayColor
    [imageInfo setObject:[NSString stringWithFormat:@"%i", i] forKey:@"arrayNr"];
    [images addObject: myImage];
    [fotoView addSubview: myImage];

    //get url
    NSURL *imageURI = [[NSURL alloc] initWithString:imageURL];

    //load image
    ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL: imageURI];

    [request setDownloadDestinationPath:[[NSHomeDirectory() stringByAppendingPathComponent:@"Documents"] stringByAppendingPathComponent:[message objectForKey:@"id"]]];
    [request setUserInfo: imageInfo];
    [networkQueue addOperation:request];

    [imageURL release];
    [imageURI release];

    [myImage release];
    [imageInfo release];

    cx = cx + 78;
    i++;
}

When the request is finished I do this:

- (void)imageFetchComplete:(ASIHTTPRequest *)request
{
    UIImage *img = [[UIImage alloc] initWithContentsOfFile:[request downloadDestinationPath]];
    if (img)
    {
        //set image
        UIButton *myButton = [images objectAtIndex:[[[request userInfo] objectForKey:@"arrayNr"] intValue]];
        [myButton setBackgroundImage:img forState: UIControlStateNormal];
        [myButton addTarget:self action:@selector(showImage:) forControlEvents:UIControlEventTouchUpInside];
    }

    [img release];
}

And this is my dealloc function:

- (void)dealloc
{
    [networkQueue cancelAllOperations];
    networkQueue.delegate = nil;
    [networkQueue release];

    [flickrController cancelAllOperations];
    flickrController.delegate = nil;
    [flickrController release];

    [images release];
    [fotoView release];
    [output release];

    [super dealloc];
}

I don't understand way the memory doesn't go away. Solution what i can think about are: - create an own object for the uibutton/uiimage. - Use an UITableview to handle the images

Both solution I don't see how it would clear all the memory after closing the view. Hope someone give me a heads-up how to handle this kind of situations.

+2  A: 

If you posted the code where you do the cleanup, it might be clearer where the problem is, but I'm taking a guess anyway:

In the imageFetchComplete: method you retain the reference to the image when you invoke setBackgroundImage: It will therefore be kept in memory until you release the particular button object that retained it. Since the button itself is being retained by the images array, you would either need to release this array too, or in case of a mutable array remove the button from the array.

Claus Broch
I put the rest of the code in my first post. What I did try was something like this at -(void)dealloc but it failed. for (UIButton* button in images) { [[button backgroundImageForState:UIControlStateNormal] release]; [button removeFromSuperview]; [button release]; }
Marko
Is the dealloc method being called?
Claus Broch
I was like why you ask that question. It's normal that dealloc get called. But it doesn't get called. So I got the problem now. Hope to find a solution for it
Marko
@Marko, it is normal that dealloc get called if you have correctly ballanced the use of retain/release. But, since dealloc doesn't get called, you need to figure out where that extra retain sneaked in.
Claus Broch
I almost never use retain. I now disabled most of the code and step by step I activate it again till the dealloc method isn't getting called again. Thanks for your help
Marko
You where right. I retain the delegate instead of assign
Marko