3

I'm curious if I'm following proper memory management with CGImageRef, which I'm passing through several methods (since it's CG object, I assume it doesn't support autorelease). Memory management with non-NSObjects and interaction with other NSObjects is still somewhat new to me.

Here what I'm doing:

I'm creating the CGImageRef inside my image cache manager with CGBitmapContextCreateImage (retain count 1), and adding it to the NSMutableDictionary (retain count 2).

When CALayers use the image, I assign with layer.contents (retain count +1), and clearing contents with layer.contents = nil (retain count -1) before removing the layer.

Finally, when clearing the texture, I call CGImageRefRelease and [NSMutableDictionary removeObject] to have retain count as 0.

Is this a proper way to do so?

Rudi
  • 2,450
  • 5
  • 26
  • 37

1 Answers1

17

Core Foundation objects (which all Core Graphics objects are) do support autorelease.

The steps you describe should work just fine and not leak or over-release the object.

I use CFRelease instead of specific-class release functions like CGImageRelease, but purely as a matter of style. I just have to beware of NULL: CGImageRelease checks for NULL, whereas CFRelease will crash when passed NULL. Using CGImageRelease and its siblings means you don't have to worry about this.

I'm assuming you meant removeObject:forKey:, not removeObject (which doesn't exist and wouldn't have somewhere to specify an object anyway).

Peter Hosey
  • 95,783
  • 15
  • 211
  • 370
  • Thanks for the link, great resource, clarifies a lot. Docs mentioned that CGImageRelease won't cause an error if image is NULL, so sounded safer to go with. removeObject:forKey:, yes, that one. – Rudi Aug 12 '09 at 00:52
  • **The document you link to doesn't support your claim.** Some Core Foundation objects are "toll-free bridged" to Cocoa classes, but not all are. You can cast a `CFStringRef` to a `NSString *` and vice versa, but you cannot do so with `CGImageRef` and `UIImage`. – benzado Dec 25 '09 at 06:53
  • My claim is that CF objects support `release` and `autorelease`. That document explicitly says so: “Note from the example that the memory management functions and methods are also interchangeable—you can use `CFRelease` with a Cocoa object and `release` and `autorelease` with a Core Foundation object.” Furthermore, the CGImage reference says that CGImage descends from CFType: http://developer.apple.com/iphone/library/documentation/GraphicsImaging/Reference/CGImage/ – Peter Hosey Dec 25 '09 at 09:28
  • So, in a nutshell, **yes it does.** – Peter Hosey Dec 25 '09 at 10:48
  • 1
    I thought it was referring to toll-free bridged objects, which are a subset of CFTypes, based on: "Table 1 provides a list of the data types that are interchangeable between Core Foundation and Foundation." Also, at the bottom of the page: "**Note:** Not all data types are toll-free bridged, even though their names might suggest that they are. For example, NSRunLoop is not toll-free bridged to CFRunLoop, NSBundle is not toll-free bridged to CFBundle, and NSDateFormatter is not toll-free bridged to CFDateFormatter." Are you saying you can cast *any* CFType to NSObject and autorelease it? – benzado Dec 25 '09 at 13:14
  • Yes. The Carbon-Cocoa Integration Guide explicitly says that “you can use … `release` and `autorelease` with a Core Foundation object”, and anything whose class descends from CFType is a Core Foundation object (as evidenced by the fact that you can use CF functions like `CFRetain`, `CFCopyDescription`, etc. on it). – Peter Hosey Dec 26 '09 at 05:21
  • This isn't the same as toll-free bridging, though. You can't say `[myCGImage performSelectorOnMainThread:@selector(…) withObject:…]`, because a CGImage is not an NSObject. – Peter Hosey Dec 26 '09 at 05:21
  • `CFRelease()` ≠ `CGImageRelease()`. I'm pretty sure `CFRelease()` will crash if you pass `NULL`, however it's safe to pass `NULL` to `CGImageRelease()` – nielsbot Jun 20 '11 at 10:01
  • @nielsbot: Good catch! I didn't know that at the time. I still use CFRelease (with `NULL` checks as appropriate) for style reasons, so I'll have to think about how to edit that into my answer. – Peter Hosey Jun 20 '11 at 10:52