One of the first subjects that causes a little bit of confusion among new Objective C programmers is that of variable naming conventions and options. Terms such as CamelCase, strong, weak, atomic, nonatomic, readonly, readwrite, ivars, and properties, can cause no small degree of confusion, but with a little bit of elucidation, I think you’ll see these terms are a lot less scary than you might think.
(Note: Please take a moment to follow me on twitter, won’t you? If you would like to hire us for your next iOS project, please drop us a line at streamside7@hotmail.com.)
Let’s Start with Properties
I won’t be able to cover every option, variation, and naming convention in this post, but I think I can hit the important points and get you headed in the right direction.
I’ll start with the subject of properties. Properties differ from variables in that they are accessed using getters and setters or through dot syntax. Properties are important to Obj-C because of the object oriented concepts of encapsulation and data hiding.
In short, an object should take care of itself. It should have a single reason for existing, it should keep its data locked away within itself, and other objects shouldn’t be able to reach into it and mess with its data.
If other objects need to access an object property, an object can expose it through its interface, and access should be done through getters and setters (or using dot syntax which is a shortcut for the same thing).
By making each object wholly dependent on itself (its own data and methods) and hiding its data, you can reprogram internals of a single object without affecting the rest of the program. Other objects only know what the object should do and how to interface with it; they don’t know how it works, nor should they know.
Properties play a big role in helping us accomplish this goal.
Additionally, by using properties, your object can manage memory, restrict who can access the property, and control how it behaves in a multi-threaded application. You can even define certain special behaviors that happen when a property is set.
Let’s start with property naming conventions and the concept of ivars or instance variables.
CamelCase, headlessCamelCase, and ivars
Rest assured; no camels were harmed in the creation of this post!
Typically properties and methods should be named using headlessCamelCase. The first letter is uncapitalized, while each new word in the property or method name is capitalized, such as “thisIsAVariableName.”
Conversely class names (and entity names in CoreData) should be capitalized while each new word is capitalized, such as “ThisIsAClass.”
Constants are named with all upper case characters.
Why? This makes classes, constants, and properties instantly discernible.
The dreaded “_” character
Now in some code you may see a property defined as something like “propertyName” and in another place see it referred to as “_propertyName.”
What’s going on here? Let’s cut to the chase. In modern Objective C, whenever you declare a property name such as this:
@property (strong) NSString *title;
Getters and setters are automatically synthesized (created), and a corresponding instance variable is created with the “_” appended to the beginning of the name, so in this case it would be “_title” as the instance variable or “ivar” name.
Instance variables or “ivars” are variables that have individual contents for each instance of an object and can only be accessed within that instance, or by other objects which use its getters or setters (or by using dot syntax).
In the above example, you can only access the “title” ivar within the instance by using “_title” or “[self title],” you can’t just access it as “title.”
Of course you can and will define your own ivars within the { and } curly braces at the top of your @implementation section, and whether you decide to start these with a “_” character is completely up to you. Since this naming practice is often debated, I won’t weigh in on it.
Old School Objective C Variables
Objective C didn’t always automatically synthesize getters and setters. In earlier days of Obj-C programming, it was common to see code such as this:
@synthesize variableName=_variableName
This creates the getters and setters for “variableName” as well as the corresponding ivar.
Tip: When I see something like this, I generally just think, “I don’t need to do this anymore.”
Readonly vs. readwrite
So what’s the difference in the following examples:
@property (readonly) NSString *title; @property (readwrite) NSString *title2;
In this case “title” is only available for reading, even by your own object, and no setter will automatically be synthesized.
“title2” on the other hand can be both read from and written to, and both getters and setters will be created, which is the default behavior. This begs the questions: if this is the default behavior, why specify it as readwrite, and if something is readonly, even to me, how do I access it.
Great questions!
A common scenario is to define a property as readonly in the interface (.h file) and reclassify it as readwrite in the implementation (.m file), which answers both questions. Thus other objects are kept from writing to your data but can still read it, while you are then free to do whatever you wish with it.
Strong vs. weak
So what’s the difference in the following examples:
@property (strong) NSString *title; @property (weak) NSString *title2;
Once upon a time, memory management was quite an involved process when working with Objective C.
Built into NSObject, the base class from which nearly every object is derived, is a reference counter that was incremented when an object was created and decrimented when an object was released. It’s a little more involved than this, but this is a very high level overview.
In short the reference counters allowed other objects to indirectly increment them as well, thus keeping an object around even when the object was released by its owner.
It’s a great scheme and circumvents the need for automatic garbage collection used by other environments.
Apple later introduced Automatic Reference Counting or ARC. ARC basically automatically inserts invisible commands like “retain” and “release” which manipulate these reference counters greatly simplifying memory management. Thank you Apple!
Still, they could only simplify it so much. Einstein famously said, “everything should be as simple as it can be but not simpler.”
Basically the compiler needs to know some things. If you want to own a property, meaning you never want it to go away, you would use the word “strong.” As long as there is one strong reference to a property, the property will stick around.
A strong reference to a property is created by default (even when you don’t define it as strong) and when performing certain operations such as assigning it to an array.
A weak reference, however, is not an owning reference. If you don’t need to own a property, you can set it to weak, and when it is released, your weak property will automatically be set to nil.
Atomic vs. nonatomic
So what’s the difference in the following examples:
@property (atomic) NSString *title; @property (nonatomic) NSString *title2;
Atomic and nonatomic comes into play when working with multi-threading. Specifying a property as atomic means that when you go to read the property, you will never get back an invalid value. This alone does not make a program thread-safe, but when working with multiple threads, it is important.
So why not make all properties atomic?
Speed! Nonatomic properties are much faster, and if you’re not using multithreading this makes them worth it.
Conclusion
That’s a brief overview. All of these topics deserve much more depth and would reward further study. I highly suggest this book if you’d like to go deeper into memory management: Objective-C Memory Management Essentials.