In the process of a chat, the basic rules of cocoa memory management came up. This led me to make a list of the basic rules, which I’ve decided to post here for no particular reason. I don’t claim this list is particularly perfect, but I think its a pretty good attempt.
- Objects instantiated by nibs (views, controllers, the likes) are automagically released when your application terminates
- If you use a convenience constructor, like + NSString#stringWithFormat:, the value is autoreleased and doesn’t need to be explicitly released. In fact, if you release an object with a retain count of 1 thats been autoreleased, you’ll get a runtime error.
- If you’re creating a lot of autoreleased objects, say in a loop, its best to create and drain an autorelease pool in the loop or around the loop to prevent unnecessary memory use.
- Any time you allocate and initialize something, you need to balance it with a release. If you’re returning a new object in an accessor, you should autorelease it. Note: its really bad practice to autorelease objects that you could easily release a few lines later, it just adds to memory use.
- Objects returned by accessors are either autoreleased, or owned by the receiver itself unless explicitly marked otherwise.
- If you don’t start your application with NSApplicationMain, or you’ve spawned a new thread, you need to create an autorelease pool before anything you do, and you need to drain it when you’re done. If you don’t create an autorelease pool, you will receive an error message and will leak memory.
If you happen to be lazy, and don’t care about leaks beyond your control, you can in fact use garbage collection in 10.5 and up. Cocoa garbage collection is very far from transparent, and only works automatically for cocoa objects and nothing else. Here are a few things to keep in mind when using garbage collection:
- CoreFoundation objects are not managed by the garbage collector. Even though it would make _a lot_ of sense, CFObjects are not automatically managed by the cocoa garbage collector even though they are internally the same as NSObjects. This means that using any CF* method that returns a new object must be released appropriately.
- Just because you use garbage collection, doesn’t mean you shouldn’t write regular memory management code, even if its no-op. In the event you need to use some code you’ve written on a system older then leopard, or you just find that you don’t like garbage collection and its ugly overheads, this will in fact come quite in handy.
- References don’t really just go away. As long as you have a reference to an object, be it an ivar, a regular variable, or in a collection the object will _never_ be destroyed which will result in a leak. Theoretically this should solve itself, but there are times when it doesn’t. If two objects are referencing each other, neither will ever be destroyed.
I wouldn’t say this is a definitive guide, its really just observations from experience. I don’t claim 100% accuracy, I am only human, and only writing this blog post as a passing fancy. But, if this can help someone[s], then thats great.