Objective-C Succinctly: Properties


Now that we've explored what data types are available, we can talk about actually using them in a productive manner. We learned how to declare properties in Hello, Objective-C, but this chapter dives deeper into the nuances behind public properties and instance variables. First, we'll take a quick look at the basic syntax of properties and instance variables, and then we'll discuss how to use behavior attributes to modify accessor methods.

Declaring Properties

Properties can be declared in an interface using the @property directive. As a quick review, let's take a look at the Person.h file we created in the Hello, Objective-C chapter:

#import <Foundation/Foundation.h>

@interface Person : NSObject

@property (copy) NSString *name;


This declares a property called name of type NSString. The (copy) attribute tells the runtime what to do when someone tries to set the value of name. In this case, it creates an independent copy of the value instead of pointing to the existing object. We'll talk more about this in the next chapter, Memory Management.

Implementing Properties

In Hello, Objective-C, we used the @synthesize directive to automatically create getter and setter methods. Remember that the getter method is simply the name of the property, and the default setter method is setName:

#import "Person.h"

@implementation Person

@synthesize name = _name;


But, it's also possible to manually create the accessor methods. Doing this manually helps to understand what @property and @synthesize are doing behind the scenes.

Included code sample: ManualProperty

First, add a new property to the Person interface:

@property (copy) NSString *name;
@property unsigned int age;

Note that we're storing age as a primitive data type (not a pointer to an object), so it doesn't need an asterisk before the property name. Back in Person.m, define the accessor methods explicitly:

- (unsigned int)age {
	return _age;

- (void)setAge:(unsigned int)age {
	_age = age;

This is exactly what @synthesize would have done for us, but now we have the chance to validate values before they are assigned. We are, however, missing one thing: the _age instance variable. @synthesize automatically created a _name ivar, allowing us to forgo this for the name property.

Instance Variables

Instance variables, also known as ivars, are variables intended to be used inside of the class. They can be declared inside of curly braces after either the @interface or @implementation directives. For example, in Person.h, change the interface declaration to the following:

@interface Person {
	unsigned int _age;

This defines an instance variable called _age, so this class should now compile successfully. By default, instance variables declared in an interface are protected. The equivalent C# class definition would be something like:

class Person {
	protected uint _age;

Objective-C scope modifiers are the same as in C#: private variables are only accessible to the containing class, protected variables are accessible to all subclasses, and public variables are available to other objects. You can define the scope of instance variables with the @private, @protected, and @public directives inside of @interface, as demonstrated in the following code:

@interface Person : NSObject {
	NSString *_ssn;
	unsigned int _age;
	NSString *job;

Public ivars are actually a bit outside Objective-C norms. A class with public variables acts more like a C struct than a class; instead of the usual messaging syntax, you need to use the -> pointer operator. For example:

Person *frank = [[Person alloc] init];
frank->job = @"Astronaut";
NSLog(@"%@", frank->job);
// NOT: [frank job];

However, in most cases, you'll want to hide implementation details by using an @property declaration instead of public instance variables. Furthermore, because instance variables are technically implementation details, many programmers like to keep all instance variables private. With this in mind, ivars declared in @implementation are private by default. So, if you were to move the _age declaration to Person.m instead of the header:

@implementation Person {
	unsigned int _age;

_age would be scoped as a private variable. Keep this in mind when working with instance variables in subclasses, as the different defaults for interface versus implementation declaration can be confusing for newcomers to Objective-C.

Customizing Accessors

But enough about instance variables; let's get back to properties. Accessor methods can be customized using several property declaration attributes (e.g., (copy)). Some of the most important attributes are:

  • getter=getterName - Customize the name of the getter accessor method. Remember that the default is simply the name of the property.
  • setter=setterName - Customize the name of the setter accessor method. Remember that the default is set followed by the name of the property (e.g., setName ).
  • readonly - Make the property read-only, meaning only a getter will be synthesized. By default, properties are read-write. This cannot be used with the setter attribute.
  • nonatomic - Indicate that the accessor methods do not need to be thread safe. Properties are atomic by default, which means that Objective-C will use a lock/retain (described in the next chapter) to return the complete value from a getter/setter. Note, however, that this does not guarantee data integrity across threads-merely that getters and setters will be atomic. If you're not in a threaded environment, non-atomic properties are much faster.

A common use case for customizing getter names is for Boolean naming conventions. Many programmers like to prepend is to Boolean variable names. This is easy to implement via the getter attribute:

@property (getter=isEmployed) BOOL employed;

Internally, the class can use the employed variable, but other objects can use the isEmployed and setEmployed accessors to interact with the object:

Person *frank = [[Person alloc] init];
[frank setName:@"Frank"];
[frank setEmployed:YES];
if ([frank isEmployed]) {
	NSLog(@"Frank is employed");
} else {
	NSLog(@"Frank is unemployed");

Many of the other property attributes relate to memory management, which will be discussed in the upcoming section. It's also possible to apply multiple attributes to a single property by separating them with commas:

@property (getter=isEmployed, readonly) BOOL employed;

Dot Syntax

In addition to getter/setter methods, it's also possible to use dot notation to access declared properties. For C# developers, this should be much more familiar than Objective-C's square-bracket messaging syntax:

Person *frank = [[Person alloc] init]; = @"Frank";    // Same as [frank setName:@"Frank"];
NSLog(@"%@",; // Same as [frank name];

Note this is just a convenience-it translates directly to the getter/setter methods described previously. Dot notation cannot be used for instance methods.


Properties are an integral aspect of any object-oriented programming language. They are the data that methods operate on. The @property directive is a convenient way to configure a property's behavior, but it doesn't do anything that can't be done by manually creating getter and setter methods.

In the next chapter, we'll take a detailed look at how properties are stored in memory, as well as a few new property attributes for controlling this behavior. After that, we'll dive into methods, which rounds out the core object-oriented tools of Objective-C.

This lesson represents a chapter from Objective-C Succinctly, a free eBook from the team at Syncfusion.
Related Posts
  • Code
    iOS SDK
    Objective-C Succinctly: Blocks0e5ds8 preview image@2x
    Blocks are actually an extension to the C programming language, but they are heavily utilized by Apple's Objective-C frameworks. They are similar to C#'s lambdas in that they let you define a block of statements inline and pass it around to other functions as if it were an object.Read More…
  • Code
    iOS SDK
    Objective-C Succinctly: Categories and Extensions0e5ds8 preview image@2x
    Categories are an Objective-C language feature that let you add new methods to an existing class, much like C# extensions. However, do not confuse C# extensions with Objective-C extensions. Objective-C's extensions are a special case of categories that let you define methods that must be declared in the main implementation block.Read More…
  • Code
    iOS SDK
    Objective-C Succinctly: Methods0e5ds8 preview image@2x
    In this chapter, we'll explore Objective-C methods in much more detail than we have in previous chapters. This includes an in-depth discussion of instance methods, class methods, important built-in methods, inheritance, naming conventions, and common design patterns.Read More…
  • Code
    iOS SDK
    Objective-C Succinctly: Memory Management0e5ds8 preview image@2x
    Memory must be allocated for each object your application uses, and it must be deallocated when your application is done with it to ensure your application is using memory as efficiently as possible. It's important to understand Objective-C's memory management environment to ensure your program doesn't leak memory or try to reference objects that no longer exist.Read More…
  • Code
    iOS SDK
    Objective-C Succinctly: Data Types0e5ds8 preview image@2x
    Objective-C has two categories of data types. First, remember that Objective-C is a superset of C, so you have access to all of the native C data types like char, int, float, etc. Objective-C also defines a few of its own low-level types, including a Boolean type. Let's call all of these "primitive data types."Read More…
  • Code
    iOS SDK
    Objective-C Succinctly: Hello Objective-C0e5ds8 preview image@2x
    This chapter is designed to help you acclimate to Objective-C programming style. By the end of this chapter, you will be able to instantiate objects, create and call methods, and declare properties. Remember that the goal is to provide a very brief survey of the major object-oriented aspects of Objective-C, not a detailed description of each component. Later chapters fill in many of the conceptual details omitted from this chapter.Read More…