Objective-C Declared Property memory management semantics in iOS

This is a topic which is difficult for a new iOS developer to understand. As an iOS developer with some experience, I also think that it is a difficult topic to explain. However, in this post, I’ll try.

Kudos to Chris Hanson from the Stack Overflow community. I have read his explanation in the past, but it wasn’t until today that I experimented in code. Then, I fully understood.

.

Which one? assign, retain, copy

When you decide to declare a property in a class, you need to specify semantics, including behaviour and memory management.

For behaviour, in iOS apps, choose nonatomic.

Note: I may edit this, after further study of, and experience with, GCD and blocks.

.

For memory management, read on.

.

assign

For primitive C types (int, float, …), use assign. Also, use assign for BOOL and NSNumber.

For a delegate, use assign. That way, you’ll avoid a “retain cycle”. (A retain cycle is bad.)

Assign is the default.

Assign can be thought of as an antonym for retain.

.

retain

If the property’s type does NOT conform to the NSCopying protocol, use retain.

Check the property type’s class reference documentation to see whether it conforms to the NSCopying protocol.

Many commonly-used types conform to NSCopying, including NSString, NSArray, and NSDictionary (and their mutable subclasses).

Notably, NSObject does not conform to NSCopying. Many model objects inherit from NSObject, so a model object property will use retain, unless the model object conforms to the NSCopying protocol (by implementing the methods discussed in the NSCopying Protocol Reference documentation).

Additionally, NSManagedObject does not conform to NSCopying. Nor will a generated subclass. Therefore, use retain.

While you will learn (below) that copy may be the most suitable option, there is a situation where you may decide that you want to use retain. Assume that your property was set to an object, maybe during initialization. And, further assume that the object can change (mutate), but you want your property to follow that change. Therefore, in this situation, you really do want to retain a reference to the object, so you must use retain.

.

copy

This may be the most suitable option for most property types.

You are assured that your property’s value can only be changed (mutated) by using its setter accessor.

.

What does this really mean?

A declared property is a convenient way to create accessors (i.e. getter and setter) for an instance variable.

Then, in a statement in your program code, you will set a value for the property. This will be done during initialization, or later.

For example, assume that you have a model class, and it has a property called “school”. In the class initializer, you wish to assign a string to the property. Here’s the code:

self.school = @”Seneca”;

In this situation, using retain or copy will be equivalent. The right side of the statement is an immutable string, so it (@”Seneca”) won’t change in the future.

However, consider a slightly different scenario to the one above. In the class initializer, you wish to assign a value that was passed in as an argument (called “someName” in this scenario), and the original value (that was passed in) is mutable. The code looks like this:

self.school = someName;

In this situation, using copy is almost always preferred. You get a copy of the original value, and the property is set to this value. If the original value changes, the property’s value will not change.

Alternatively, if you use retain, and change the original value, the property’s value changes too. That’s probably a bad thing. (You almost always want to use the property accessor to mutate its value.)

This scenario also applies outside of the initializer. That is, when you create an instance of your model object, and set the instance’s property value, the same retain and copy behaviour applies.

.

Advertisements
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: