Owning Up – Release, Retain, and Object Ownership

by Rob Bajorek on July 21, 2009

Ever used the NSString class? If you’re reading this, you probably have. Let’s look at a couple of ways to create NSStrings with the …WithFormat: methods.

- (id)initWithFormat:(NSString *)format
Returns an NSString object initialized by using a given format string as a template into which the remaining argument values are substituted.

+ (id)stringWithFormat:(NSString *)format,
Returns a string created by using a given format string as a template into which the remaining argument values are substituted.

Hmm, they both sound about the same, take the same arguments, and return an NSString object.  Apple made these two functions for a reason, so what’s the difference?

There are semantic differences in usage, but the real difference I’m talking about is who owns the NSString object.

Object Ownership in Objective-C

From the object’s perspective, what does it mean to be owned?  According to Apple’s Memory Management Guide, an object exists as long as it has at least one owner.  There are no restrictions on how many owners an object has; it can have none or a hundred.  An owner relinquishes ownership by sending their object a release or autorelease message.  When the last owner has given up ownership, the application will dispose of the object automatically.

How do you know if an object is yours?

  • If you create an object with alloc, new, or copy, it’s yours.
  • If you retain an object, it’s yours.
  • Everything else is not yours.

That’s it.

What does that mean?  The main point of object ownership is you choose to own an object because you don’t want it deallocated.  If an object is not yours and you want to keep it around, you must retain it and make it yours.  Otherwise, the system may take it away from you.

We’re also talking about memory managementYou must clean up after yourself.  If an object is yours and you’re done with it, you must release or autorelease it.  If you don’t, you create a leak: allocated memory that cannot be freed because you’ve lost the reference to it.  Leaks cause memory problems, and if this is an iPhone app then Apple may reject it until you fix the mess.

An example

Here’s a snippet that demonstrates different ownership situations.

/* Create some strings */
int count = 1;

NSString *string1 = [[NSString alloc] initWithFormat:@"This is string %d. It's mine, so I need to release it when I'm done.", count];
count++;

NSString *string2 = [NSString stringWithFormat:@"This is string %d. It is not mine, so I won't release it.", count];
count++;

NSString *string3 = [[NSString stringWithFormat:@"This is string %d. We are retaining it, so we must release it later.", count] retain];
count++;

... // code using the strings snipped

/* Done with the strings, get rid of them */
[string1 release];     // Released and gone
// [string2 release];  // string2 is not ours, so releasing it is an error
[string3 autorelease]; // Still here until NSAutoReleasePool is drained

The string1 object is created with alloc and initialized by initWithFormat:.  Checking the rules, alloc is one of our special keywords, so string1 is ours.  We need to release it, and in fact we do so.  No problem.

Our string2 object is created with the NSString factory method stringWithFormat:.  The method name doesn’t use the ownership keywords, so string2 is not ours.  It will be autoreleased.  In fact, if you release it…

Program received signal:  “EXC_BAD_ACCESS”.

Oops!  Don’t do that!

Lastly, string3 is an autoreleased string like string2, but this time we retained it. Using retain takes ownership of it, so string3 is ours.  We need to release it when we’re finished with it.  This time though, we chose to autorelease it.  We don’t own it anymore, but it’s still around.

Release vs. Autorelease

As we’ve seen, there are two ways to disown an object: release and autorelease.  What’s the difference?

If you use release, the effect is immediate.  If you were the last owner, that object is gone and memory is freed.

CSWidget *widget = [[CSWidget alloc] init];  // New widget, owned by me
[widget shake];
[widget twirl];
[widget release];  // widget is gone

Usually this is fine, but that may not be what you want.

Take “(NSString *)stringWithFormat: (NSString *)format, …” .  How can stringWithFormat: disown its returned object without losing it?  By using autorelease.

+ (CSWidget *) widget {
  CSWidget *widget = [[CSWidget alloc] init];  // New widget, owned by me
  [widget autorelease];  // Not owned by me anymore, but still exists
  return widget;
}

We created a widget object and disowned it, but its release is delayed until the current NSAutoReleasePool is drained. That is a subject for another post, but simply, the pool is drained after every pass of the main event loop.

Short version: release = immediate, autorelease = delayed.

For the Mac folks

On Mac you can use garbage collection now, so should you put in retain and release messages if they are just no-ops? Generally no, but with one exception.  If there’s a chance you’ll port your Mac code to iPhone, I would consider using reference-count rules.  If you don’t, you’ll have to go through the code again and fix it up to work on iPhone.

More information

I recommend reading the Memory Management Programming Guide for Cocoa for a complete explanation of object ownership and memory management.

Review

  • Know the ownership keywords (alloc, new, copy, retain)
  • Retain objects you want to keep
  • Don’t release objects that aren’t yours
  • Use release when you don’t care if an object is deallocated immediately
  • Use autorelease to give up ownership but delay an object’s release

Good luck!

0 comments

WWDC 2009 Videos Released

by Rob Bajorek on June 29, 2009

For all of you WWDC attendees and Premier ADC members, good news!  The WWDC 2009 videos are now available!

I heard rumors that this was going to take a couple of months, so I’m very happy that they are already on iTunes U.

Now if you’ll excuse me, I’m going to catch the OpenCL and Grand Central Dispatch sessions I missed the first time!

Click here for ADC on iTunes and the videos.  (WWDC 2009 attendees and Premier ADC members only.)

0 comments

Five Points From Attending WWDC 2009

by Rob Bajorek on June 18, 2009

Front entrance of Moscone West at WWDC 2009

I’m back home from Apple’s Worldwide Developers Conference in San Francisco.  It was my first time, and a fun, productive experience.  There are some great posts about WWDC that I read before I went, but here are some more things I noticed:

#1 — If you don’t live for the keynote, just fly in Monday morning

I heard stories about crazy lines for the keynote, so my friend and I decided to just show up around 9:30.  When we arrived, they weren’t letting people in yet and the line wrapped around the whole convention center.  Forget that!  We went to a coffee shop, followed a live Twitter feed, and went back around 10:20.  Much better, walked into the overflow room and saw almost all of the show.  Next year I’m coming to SF on Monday morning and joining the overflow crowd again.

#2 — It’s easy to make friends…

… but most people there aren’t going to strike up a conversation.  It’s up to you to make the first move.   It’s ok!  Mac geeks are friendly and you can meet some interesting people.  (However, I didn’t have anyone come up to me who wasn’t trying to sell me something, so please don’t be that person.)

#3 — Don’t pass out business cards to random people

This concept is Business 101 in my opinion, but I don’t offer my business card to someone unless we’ve established a relationship.  Handing out cards to people walking by is just wasting money and generating ill will.   A few guys were doing this inside Moscone West; their cards went right in the trash.

#4 — Know where to find power outlets

Power strip from seating at WWDC 2009
If you’re at WWDC, you probably have a laptop.  I was worried about keeping charged throughout the day, but it wasn’t a problem at all!

The session rooms had power strips like the one pictured mixed in with the seats. They weren’t always in every row, so sometimes you would plug into the row behind.  When you’re roaming Moscone West, there were a number of tables with power strips, as well.  Also, in the hallways there were small clusters of power outlets in the walls that many people overlooked.

#5 — Almost every seat is a good one

The display screens were very large and the acoustics good in every room. Unless you want to see the speakers up close, you can sit pretty much anywhere.

For the heck of it, I did sit in the front row for one session.  I ended up with a sore neck from trying to see the screen.  Just sit in the middle.

Anything else?

Feel free to post your own comments and accumulated wisdom from WWDC!

0 comments

Some folks have asked me for examples of how my Cheetah3D -> iPhone header converter works. To help you out, I’m posting an Xcode project that I’m using to test the converter.

You can get it here: C3DConverterTest.tgz

This project renders four different shapes generated in Cheetah3D. It’s pretty simple; a lot of the code is from the Xcode’s standard OpenGL ES project template. I’ve added lighting to show that the normals work properly, though.

Some notable files:

  • 4 shapes.jas — the Cheetah3D project
  • 4 shapes.h — the header file exported from Cheetah3D. You can run this through the converter yourself if you like.
  • 4 shapes_iphone.h — the header file made by my converter
  • pure_colors.jpg — A simple texture. Replace this with your own for a different look.

I hope this helps!  Let me know if you have questions or comments.

0 comments

I’ve updated the Cheetah3D -> iPhone header file converter to version 2.0.1.  This version corrects object names from Cheetah3D that aren’t valid in Objective-C.  (Example: “Box.1″ is renamed to “Box_1″).  Thanks to reader Scott for pointing out the problem and a solution.

Download version 2.0.1 here: c3d_to_iphone.pl (zipped)

Please comment or contact me with any feedback!

0 comments