Properties have only appeared in Objective-C recently, with the 2.0 release. They are kind of virtual member variables. If you think about it, there are only two things you can do to a variable: assign a value and extract a value. You can make variable a constant to prevent it from being set, or hide it by making it private or protected, but in no way does setting a member variable’s value affect the behavior of an object. Properties do not have to do that but they can. In Object Oriented Languages, member variables describe the state of an object, while functions (methods, messages) describe its behavior. Properties allow us to morph together the state and the behavior.
Consider the following code:
After you declare a property in Objective-C, you have to tell the compiler to instantiate it by using @synthesize directive. This actually tells the compiler to generate a getter and a setter messages. By default, these messages are named var and setVar, where var is a name of the variable. Also, by default, the variable represented by the property has the same name as a property. In our example, the compiler will generate the following:
As you can see from the Test0 example, properties can be accessed by using the DOTted notation. They can also be accessed via accessor methods, for example [self setIVar:5] or int i = [self iVar].
We can add simple permissioning by specifying readonly attribute instead of readwrite.
This would prevent the property from being assigned to. You can still change the value of the corresponding member variable, though, by referencing it directly. For example, I can add a message foo:
Here, we are actually telling the property to latch to different a different instance variable.
I showed all these examples is to show you how to use the properties to describe the state of an object.
As I mentioned previously, compiler generates accessors for each property. Read-write properties get both a getter and a setter, while read-only properties get only a getter. Getters and setters are messages, and if overwritten, can be used to do virtually anything.
When we defined a setter, we told the compiler that it does not need to generate another one. Notice how we called [self foo]. We just altered the behavior of the object.
Another way to achieve similar results is by using @dynamic directive. @dynamic tells the compiler not to generate the accessor messages and that we will do it ourselves either by directly defining them or through introspection.
Here, we actually went a step further. As you can see, we don’t even have to alter the state. We can simply alter the behavior of the object!
In reality, accessors don’t even need to be named in default fashion. We can provide our own names by using getter and setter attributes.
We already saw a few attributes, such as readwrite and readonly, getter and setter. Here are some other attributes:
These attributes are pretty self explanatory. They have to do with the way instance variables are assigned. They are also mutually exclusive. assign enforces a brute-force assignment of a value, retain retains a pointer, and copy assigns a copy of the original.
Imagine this:
The setter method generated will look like this:
What if we decided to assign-by-copy:
When would we want to do copy assignment? When there is a possibility that inSVar is mutable. Since NSMutableString derives from NSString, we may have a problem if the behavior of the object depends on immutability of sVar. You can find out more about this from "Advanced Strings in Cocoa" article [4].
By default, property assignments are atomic, i.e. they are mutexed to guarantee thread-safety. Atomicity is a nice feature, but hardly ever needed if application is not multithreaded or you guarantee thread-safety on your own. Therefore, it’s a good practice to use nonatomic attribute, while providing own thread-safety.
There is an interesting side-effect to assigning nil to a pointer property. What happens when I execute the following code?
The side-effect of this code is that iVar is not only properly released, but the iVar now points to a nil value. Therefore, [iVar release] WILL NOT crash the code.
The purpose of this article was to give a general introduction to properties. There is more to learn about properties that I was able to discuss. For more details, please refer to “The Objective-C 2.0 Programming Language” guide.
Code for this article can be found here. [5]
10/17/2008
Vladimir Pasman
Links:
[1] http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/
[2] http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSAutoreleasePool_Class/
[3] http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/
[4] http://www.cocoacast.com/?q=node/87
[5] http://www.cocoacast.com/codelibrary/ObjectiveCProperties.zip