Picture of Brian Love wearing black against a dark wall in Portland, OR.

Brian Love

Synthesize by Default with Xcode 4.4

Objective-C is a great programming language, and has had support for declaring class properties via the @property keyword.

Using a property provides accessor (getter and setter) methods in your class, without having to write them. It is very important to use accessor methods with object-oriented programming as it ensures encapsulation of data within a class. That means that there is no way for an outsider to modify class instance variables without using the getter/setter. As a programmer, you can implement these getter and setter methods in your class, allowing you control over the values that are stored in your class.

Previously in Objective-C, we were often writing both an @property keyword in our interface (.h file), as well as a @synthesize keyword in our implementation (.m file). New in Xcode 4.4 (and the new LLVM clang compiler), we no longer need to synthesize our properties. They are done for us when we compile our code!

Basics of properties

Let’s start with the basics of declaring class properties. We declare a property in our interface using the @property keyword, followed by some attributes, the type and the name:

@property (attributes) type name

For example, let’s define an array called “posts” in our PostsController.h file:

@interface PostsController : UIViewController
@property (strong, nonatomic) NSArray *posts;
@end```objectivec


Normally, we would also synthesize the property in our implementation (.m file) as well:

```objectivec
@implementation PostsController
@synthesize posts = _posts;
@end

This would be equivalent to defining two methods in our class, one for accessing (getting) the posts array, and one for mutating (setting) the posts array from outside of our PostsController object. Best practices indicate that our getter method should be simply named after the property, in this case the method would be named “posts”, so one might call the method on an instance of our PostsController class like this: [postsController posts]. And, the setting method should be named setProperty:. In this case the method would be named “setPosts”, so one might call the method on an instance of our PostsController class like this: [postsController setPosts:newPosts]. Here is what the two methods would look like if we explicitly wrote the accessor methods ourselves.

@implementation PostsController {
    NSArray *_posts;
}
-(NSArray *) posts {
    return _posts;
}
-(void) setPosts: (NSArray *)posts {
    _posts = posts;
}
@end

Synthesize by Default

Beginning with Xcode 4.4 (OS X 10.8 and iOS 5.1), we no longer need to use the @synthesize keyword. We simply declare the @property in our interface, and Xcode takes care of the rest; creating the necessary instance variable as well as the accessor methods. This is done when compiling our code using the new LLVM compiler (clang) when we do not explicitly define these ourselves. We can still declare the accessor methods ourselves if we want to override this default behavior. You do not have to do anything special in Xcode to make this happen.

Instance Variable Naming

Instance variables are now prefixed with the ”_” character, which you can still access within the class itself.

@interface PostsController : UIViewController
@property (strong, nonatomic) NSArray *posts;
@end

@implementation PostsController
  /*Be default, the synthesis uses the "_"prefix
  It would behave as if we had coded this: /*

  @synthesize posts = _posts;
@end

Keep in mind, that if you write your own accessor methods (both getter and setter), then the instance variable is not created for you, and you have to define the instance variable yourself.

What if you have existing code that already defines the synthesis of the property, without the _prefix? To preserve this backward compatibility, if you declare your @synthesize property without defining an instance variable name, then it will continue to use that name (without the ”_” prefix). For example, the following code would still work just fine.

@interface Person : NSObject
@property (strong, nonatomic) NSString *firstName;
@property (strong, nonatomic) NSString *lastName;
@end

@implementation Person
@synthesize firstName, lastName;

-(NSString *)fullname {
  return [NSString stringWithFormat:@"%@ %@", firstName, lastName];
}
@end

You can read more about the declaring of properties in Xcode an Apple’s developer site. You can also read more about the new features of Xcode 4.4.