@interface AQBlog : NSBlog @end

Tutorials, musings on programming and ePublishing

Memory Management in Objective-C


An article on the Fun with Objective-C Tumblr today talks about learning Objective-C.

This is something any experienced Cocoa developer has been asked at least half a dozen times:

“What’s the best way to learn Objective-C/Cocoa?”

I have two answers to this question:

1. Be curious
2. Don’t be satisfied

There's plenty to read in the full article, but it finishes with the following epithet:

1. Know what a pointer is.
2. Memorize the memory management rules.
3. Never invoke -retainCount.

The second item there is one I'm frequently told is ‘really difficult’ to understand. It's not. It's really not. It looks like this:

  • Only the owner of an object needs to even think about its memory management.
  • You only own an object if you get it from a method whose name begins with any one of:
    • alloc, including +allocWithZone:
    • new, including +newSomethingSomething
    • init, including -initWithSomeParameter (er, no, it doesn't. I'm being stupid. Sorry.)
    • copy, including -copyWithZone: or -mutableCopy or -mutableCopyWithZone:
  • You also ‘own’ an object (technically, you own a single reference) if you send it the -retain message.
  • If the object doesn't come from a method matching those rules, you don't own it.

Edit: Specifically, the method must either be one of the above words, or begin with one followed by an uppercase letter. This means that +newSomething returns an owned reference, but +newestSomething does not. Thanks to Dave DeLong for reminding me of this via email.

It's that simple. If you call a method beginning with alloc, new, init, or copy, then you must use -release (or -autorelease) to balance that call. If you don't call one of those methods, you Needn't Care.

How about CoreFoundation? That's even simpler: you own an object if it comes from a method containing Create. The same thing could be said about Copy, but CoreFoundation's copy constructors are always careful to frequently already contain Create, so we don't need to. Anything named using Get returns an already-managed reference, so you don't need a CFRelease for it.

Edit: I'm reminded by Peter Hosey that many CF-style APIs outside of CoreFoundation itself tend to use Copy without Create, for instance those in CoreGraphics. Note however that not everything that looks like a CF object really is one— many are just C wrappers around Carbon-era C++ code.

See? Easy. A list of four keywords in Objective-C code indicate the only times you need to ever think about memory management. And one keyword in CoreFoundation to tell you the same.

Now, there are exceptions– usually when something missed the boat, or when an existing API needed to be changed to fix an internal memory-management issue. The documentation will tell you about these very rare cases, but the best way to catch them for now is judicious use of Build & Analyze. The Clang compiler's static analysis tool knows all about these rules, and can be told about any differences to them by any API. It will tell you explicitly if you've released something you don't own, or have failed to release something you do own. Use it. Love it.

Memory management in Cocoa isn't difficult. There are rules, but they're simple and easy to remember. The main thing to remember is:

Don't over-think it.