- The Stack
- The Heap
- Pointer Variables and Object Ownership
- Strong and Weak References
- Properties
- For the More Curious: Property Synthesis
- For the More Curious: Autorelease Pool and ARC History
For the More Curious: Property Synthesis
When explaining properties in this chapter, we noted that a property automatically generates the implementation for the accessor methods and it declares and creates an instance variable. While this is true, we omitted the fact that this behavior is only the default and you have other options.
Declaring a property in a class interface only declares the accessor methods in a class interface. In order for a property to automatically generate an instance variable and the implementations for its methods, it must be synthesized, either implicitly or explicitly. Properties are implicitly synthesized by default. A property is explicitly synthesized by using the @synthesize directive in an implementation file:
@implementation Person // Generates the code for -setAge: and -age, // and creates the instance variable _age @synthesize age = _age; // Other methods go here @end
This is how properties are automatically synthesized. The first attribute (age) says “create methods named age and setAge:,” and the second attribute (_age) says “the instance variable that backs these methods should be _age.”
You can optionally leave off the variable name, which creates a backing variable with the same name as the accessors.
@synthesize age; // Is the same as: @synthesize age = age;
There are cases where you do not want an instance variable to back a property and therefore do not want a property to automatically generate the accessor method implementations. Consider a Person class with three properties, spouse, lastName, and lastNameOfSpouse:
@interface Person : NSObject @property (nonatomic, strong) Person *spouse; @property (nonatomic, copy) NSString *lastName; @property (nonatomic, copy) NSString *lastNameOfSpouse; @end
In this somewhat contrived example, it makes sense for both the spouse and lastName properties to be backed by an instance variable. After all, this is information that each Person needs to hang onto. However, it does not make sense to hold onto the last name of the spouse as an instance variable. A Person can just ask their spousefor their lastName, so storing this information in both Person instances is redundant and therefore prone to error. Instead, the Person class would implement the getter and setter for the lastNameOfSpouse property like so:
@implementation Person - (void)setLastNameOfSpouse:(NSString *)lastNameOfSpouse { self.spouse.lastName = lastNameOfSpouse; } - (NSString *)lastNameOfSpouse { return self.spouse.lastName; } @end
In this case, because you have implemented both accessors, the compiler will not automatically synthesize an instance variable for lastNameOfSpouse. Which is exactly what you would hope for.