Objective-C: Property Accessors vs. Dot Syntax

A coworker surprised me today with a really odd bit of code. I have reproduced the pertinent bit below.

@interface ViewController : UIViewController
@property (nonatomic, readonly, getter = isActive) BOOL active;
@end
@implementation ViewController
// ... Unimportant details...
- (void)viewDidAppear:(BOOL)animated {
    if (self.isActive) { // ... huh?

    }
}

At first glance there may not be anything odd about this to you. It’s pretty clear that isActive is the getter for the active property, and it compiles and runs just fine. But I suggested that he should write self.active instead of self.isActive. The only problem is that both ways–his and mine–work correctly. And so, I was struggling to explain why–in meaningful terms–he should change what he’s doing if there’s no obvious problem with how he’s using Objective-C’s Dot Syntax.

To do that, let’s review some basic Dot Syntax.

Basic Dot Syntax

Class clazz = self.class; // Getter
self.title = @"Title"; // Setter

Dot Syntax is really helpful for using properties, which are methods that can be read from and written to as if they were variables, using a friendly syntax (aka “Syntactic Sugar”). Basic properties are composed of a pairs of methods: a getter and a setter.

Getter methods in Objective-C must take no inputs and return a non-void type, and usually they are the same as the name of the property. So self.class is equivalent to [self class] because the class method has no inputs and returns a Class object.

A typical getter method might look like this :

- (NSString *)title {
    return title;
}

Similarly, setter methods take exactly one input and return void, and have the method name beginning with ‘set’. Thus the two statements are equivalent:

self.title = @"Title";
[self setTitle:@"Title"];

And the underlying set method looks like this, regardless of which syntax you used:

- (void)setTitle:(NSString *)newTitle {
title = newTitle;
}

Intermediate Dot Syntax

As a responsible and mature iOS programmer, you will usually define explicit properties for every method you intend to access using the dot syntax, because properties make it easy to allow the compiler to synthesize all your setters and getters instead of writing them out yourself. But you can always call a method that has a conforming method signature by using the dot syntax, even if it was never declared as a property.

What does that mean? It means that even though alloc and init are not properties, both take no inputs and return an output, so the following two statements are equivalent, even though the second statement looks horrendous:

NSString *test1 = [[NSString alloc] init];
NSString *test2 = NSString.alloc.init;

It is very unfortunate when you discover someone who actually prefers the latter. In general the consensus of sane developers is that properties shouldn’t be used like this, although I’m virtually certain that loads of people would feel comfortable writing NSString.new, which is itself equivalent to [[NSString alloc] init]. Or at least it’s probably equivalent. One never knows with class clusters…

Advanced Dot Syntax

Anyway, let’s go back to the property that I started with:

@property (nonatomic, readonly, getter = isActive) BOOL active;

What this means is that there is a property called active whose underlying getter method is not -(BOOL)active but rather -(BOOL)isActive, and who doesn’t have a setter (because it’s read only). The is- prefix is a common convention for any method that returns a boolean.

So given that I have a property whose getter is known to be isActive, is the proper dot syntax self.active or self.isActive? Let’s ask the compiler.

if (self.isActive) { /* Compiles! */ }
if (self.active) { /* Also Compiles! */ }

XCode, you are not helping! >:|

What’s happening is that the compiler is smart. Just as the compiler knows that self.title = @""; needs to be interpreted as a call to [self setTitle:@""];, both self.active and self.isActive are being interpreted as [self isActive].

You can see this more easily if, instead of using the dot syntax, you switch back to normal method messaging.

if ([self isActive]) { /* Compiles! */}
if ([self active]) { /* Doesn't Compile! */}

Finally, I can at least tell the difference!

So in the end, what did I tell my coworker to convince him to use self.active instead of self.isActive?

  1. He definitely should use one or the other, but not both.
  2. Because of his property definition, Dot Syntax allowed him to call [self isActive] by writing self.active
  3. If he wasn’t going to call self.active, why did he name the property active in the first place?

In the end, he ended up by only calling self.active.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s