Cocoa Programming for Mac OS X - Aaron Hillegass [43]
Figure 7.5 is an object diagram of what you have done. Note that we are going to be using half-arrows to represent bindings.
Figure 7.5. Object Diagram
Properties
As you can guess, we spend a lot of time calling accessor methods, so much so that Objective-C gives programmers the option of calling accessors by using dot notation. If you have a pointer rover to an object with a getter method rex, you can call it like this:
NSLog(@"Rover's rex is %@", rover.rex);
To call setRex:, you could do this:
rover.rex = [NSDate date];
Objective-C programmers have varying opinions about whether dot notation is a good addition to the language. Some consider it syntactic sugar, a feature that can (dangerously) disguise message sends, which do not behave the same as, say, assigning values in a structure. Others think that those dangers are outweighed by the brevity it brings to the language. For clarity, we won’t be using it in this book.
What about writing the accessor methods? If your object has 12 instance variables, do you need to write 12 setters and 12 getters?
Properties provide a very elegant way to eliminate a lot of this code. In the KvcFunAppDelegate.h file, replace the declaration of the fido and setFido: methods with the declaration of a property:
@interface KvcFunAppDelegate : NSObject int fido; } @property (assign) IBOutlet NSWindow *window; @property (readwrite, assign) int fido; - (IBAction)incrementFido:(id)sender; @end This one line is equivalent to declaring setFido: and fido methods. In KvcFunAppDelegate.m, you can use @synthesize to implement the accessor methods. Delete your fido and setFido: methods from KvcFunAppDelegate.m, and replace them with this line: @synthesize fido; Note that everything still works. (Naturally, you won’t see the log statements anymore.) The @synthesize directive implements the accessor methods for fido as they are described in KvcFunAppDelegate.h. Attributes of a Property @property (attributes) type name; The attributes can include readwrite or readonly. The default is readwrite. A property marked readonly gets no setter method. To describe how the setter method should work, the attributes can also include one of the following: assign, strong, weak, copy. Let’s look at each in turn: • assign (the default) makes a simple assignment happen. This attribute is most commonly used for scalar, nonpointer types, such as integers and floating-point values. • strong says that this property is a strong reference. It keeps the object being pointed to from being deallocated while this pointer is set. It is specific to ARC code; if you are not using ARC, the retain attribute is equivalent. • weak denotes a weak reference. It is similar to assign, except that once the object being pointed to is deallocated, this property will be set to nil. It is supported only by code compiled with ARC. • copy makes a copy of the new value and assigns the variable to the copy. This attribute is often used for properties that are strings and other classes with mutable subclasses. Attributes can also include nonatomic. If your application is multithreaded, it is sometimes important that your setter methods be atomic. That is, the execution of the setter method from one thread will not conflict with the execution of the same setter method on another thread. By default, the @synthesize call will generate accessors with this property. This involves using a lock to ensure that only one thread at a time is executing the setter. Creating and using the locks introduces some overhead. If you know that the accessors for a property don’t need to be atomic, you can eliminate the overhead by adding nonatomic to the attributes. If a property name exactly matches the corresponding instance variable name, you can simply @synthesize that name: @synthesize fido; If, however, you prefer to use a prefix with your instance
In general, the declaration of a property looks like this: