3

I have a method that constantly loads new image data from the web. Whenever all data for an image has arrived, it is forwarded to a delegate like this:

NSImage *img = [[NSImage alloc] initWithData:dataDownloadedFromWeb];
if([[self delegate] respondsToSelector:@selector(imageArrived:)]) {
    [[self delegate] imageArrived:img];
} 
[img release]; 

In imageArrived: the image data is assigned to an NSImageView:

- (void)imageArrived:(NSImage *)img
{
    [imageView1 setImage:img];
}

This works nicely, the image is being displayed and updated with every new download cycle. I have profiled my application with Instruments to ensure that there is no leaking - it doesn't show any leaking. However, if I check with Instruments' Activity Monitor, I can see my application grabbing more and more memory with time, roughly increasing by the size of the downloaded images. If I omit [imageView1 setImage:img], memory usage stays constant. My question is: how is that happening? Is my code leaking? How does the NSImage instance within NSImageView determine when to release its data? Thanks for your answers!

carsten
  • 31
  • 2
  • 2
    Are you sure it is the images that is eating your memory. If there are no leaks happening maybe old data is being kept somewhere else but still being referenced so not causing a "leak". The image on a NSImageView certainly has the normal retain/release characteristics. – vickirk Apr 05 '11 at 09:50
  • 1
    Try setting the cache mode of the `NSImage` to `NSImageCacheNever`; but the cache should be released with the object when you replace it. – 一二三 Apr 05 '11 at 10:11
  • Thank you, this is indeed what happened: the downloaded data was additionally stored into an internal array without releasing it. My apologys. Can I somehow delete my unnecessary question? :) – carsten Apr 05 '11 at 11:15
  • You can flag it and ask the moderation to delete it. –  Apr 05 '11 at 22:32

1 Answers1

1

When you do initWithData, the retain count on the data is incremented by one. Releasing the image does not change the retain count on the data. That's where your memory is going. The image structures are coming and going the way you want, but the data chunks are accumulating.

save the data handle separately and clean that out after disposing of the nsimage, and all should be well:

(id) olddata = 0; // global or something with persistence
your_routine
{
    (id) newdata = dataDownloadedFromWeb;
    NSImage *img = [[NSImage alloc] initWithData: newdata];
    if([[self delegate] respondsToSelector:@selector(imageArrived:)])
    {
        [[self delegate] imageArrived:img];
    }
    [img release];
    if (olddata) [olddata release];
    olddata = newdata;
}

cleanup
{
    if (olddata) [olddata release];
    olddata = 0;
}
fyngyrz
  • 2,458
  • 2
  • 36
  • 43