Skip navigation.
 
mlFixing my massive memory leak with NSImage/CALayer
FROM : Nathan Vander Wilt
DATE : Tue Apr 01 20:07:24 2008

I want to pop up photographs inside their own Core Animation layers, 
but I get huge real memory usage that never goes down.

I have an FRPhoto class whose instances manage other metadata for the 
image, and also have a convenience method to get an NSImage* as follows:

- (NSImage*)image {
   if (!cachedImage) {
       cachedImage = [[NSImage alloc] initByReferencingFile:filename];
   }
   return cachedImage;
}

...which I use to show the photo, in my view's method:

- (void)showPhoto:(FRPhoto*)photo {
   CALayer* layer = [CALayer layer];
   CGImageRef image = [[[[photo image] representations] objectAtIndex:0] 
CGImage];
   layer.contents = (id)image;
   layer.frame = CGRectMake(0.0f, 0.0f, 50.0f, 50.0f);
   layer.contentsGravity = kCAGravityResizeAspect;
   [interactionLayer addSublayer:layer];
   [layersForPhotos setObject:layer forKey:photo];
}

To put the FRPhoto into the layersForPhotos dictionary, I just 
implemented a lazy retained "copy":

- (id)copyWithZone:(NSZone*)zone {
   (void)zone;
   return [self retain];
}

These FRPhoto instances are kept basically indefinitely, so when I 
hide the photo (also in the view) I make sure to call -[NSImage 
recache]:

- (void)hidePhoto:(FRPhoto*)photo {
   CALayer* layer = [layersForPhotos objectForKey:photo];
   [layersForPhotos removeObjectForKey:photo];
   [layer removeFromSuperlayer];
   layer.contents = nil;
   [[photo image] recache];
}


So by my reckoning: The CALayer should be autoreleased. And its 
contents, too, were supposed to be an autoreleased CGImage, and I set 
that property to nil just in case the layer itself is somehow sticking 
around. The NSImage that my FRPhoto holds on to should have 
"invalidate[d] and free[d] the offscreen caches of all image 
representations". But yet my memory usage just goes up and up and up, 
every photo I view. Images I have looked at already pop right back up, 
so they definitely act like they're still cached somewhere.

Even after many non-photo-showing event cycles, or just leaving it be 
for a few minutes, absolutely no significant amount of memory has been 
released according to both Instruments' ObjectAlloc and the Activity 
Monitor. By the time I've look at a dozen images my RAM is totally 
overwhelmed, making iPhoto's 15 second beachballs every couple minutes 
look pretty attractive, compared to total system-wide gridlock.

What am I doing wrong? How can I get these images out of memory?

thanks,
-natevw

Related mailsAuthorDate
mlFixing my massive memory leak with NSImage/CALayer Nathan Vander Wilt Apr 1, 20:07
mlRe: Fixing my massive memory leak with NSImage/CALayer Jens Alfke Apr 2, 01:24
mlRe: Fixing my massive memory leak with NSImage/CALayer Nathan Vander Wilt Apr 2, 04:47
mlRe: Fixing my massive memory leak with NSImage/CALayer Jens Alfke Apr 2, 07:32