Konstantin Anoshkin

Objective-C Properties and Coding Style

Objective-C 2.0 introduced a nice thing called properties. In this post, intended for beginning Objective-C developers, I will try to explain what properties are and how not to misuse the syntax.

Objective-C 2.0 Properties

Objective-C properties help readability a lot, making interface declarations more self-descriptive. They also help you make your code a little cleaner by replacing some of the square brackets with the dot notation where appropriate. All in all, Objective-C 2.0 properties encourage a better coding style, but their use requires a little understanding and discipline.

Consider the following class interface and particularly the property declaration:

Property declaration
1
2
3
4
5
6
7
8
9
@interface Container : NSObject
{
    @public
    float _weight;
}

@property (nonatomic, assign) float weight;

@end

This declaration says that you can both get and set the weight of a container object (indicated by readwrite attribute or by the absence of readonly attribute), that the value type is float and that it is not safe to use the property as is in multithreaded scenarios (nonatomic means there are no locks involved). That’s a whole lot of useful information in a single line.

Dot Notation

When you need to access the weight property, you write myBag.weight = 2000.0f. Nothing could be simpler, right? Not quite. An attentive mind will notice the dot between the object and the property name and say,

Objective-C is a thin layer on top of C, and moreover is a strict superset of C…

Yep.

In C we use a period to access a member of a struct, like stat.st_size.

Yep.

Objective-C objects are in fact C pointers and id is declared as a pointer to a C struct.

Yep:

objc/objc.h
1
2
3
typedef struct objc_object {
    Class isa;
} *id;

What the heck, then, does myBag.weight mean? Is myBag a struct, a pointer or what?

Okay. Glad you noticed that. Now – if you want to retain your sanity – forget about what id is. It’s a generic Objective-C object, its size is equal to the size of a pointer (well, the grass is green, the sky is blue, a pointer has the size of a pointer) and that’s all you need to know. You are not supposed to know what id actually is, got that? Now, the dot in Objective-C, being the same symbol as a period in C, is a special syntax to access object properties. Don’t confuse it with accessing a member of a struct, because id is not a struct. Don’t confuse it with accessing an object’s instance variables either, because a property in general has no correlation with any instance variables. A property is just that, a property.

One day, when you become proficient in Objective-C, you will write something like this:

Properties vs Ivars
1
2
3
Container *aBag = [Container new];
if (aBag.weight != aBag->_weight)
    NSLog(@"*** Accessor method returned a different weight");

Notice that aBag.weight is the value of the property and aBag->_weight directly refers to the instance variable called _weight. Don’t do it unless this is your class and you know what you’re doing and there’s no other way to do it. Bad me, I’m teaching you horrible things. Sorry. I just want to point out that a property is not the same thing as an instance variable, even if they happen to have the same name. More on that a bit later.

Accessor Methods

More often than not you probably just @synthesize the property and forget about it. But wait, you don’t use something unless you know what it does, right? So what does @synthesize do? According to the official documentation,

You use the @synthesize directive to tell the compiler that it should synthesize the setter and/or getter methods for a property if you do not supply them within the @implementation block.

In other words, @synthesize tells the compiler to generate Objective-C methods which more or less look like this:

Accessor Methods
1
2
3
4
5
6
7
8
9
- (float) weight
{
    return _weight;
}

- (void) setWeight: (float) newValue
{
    _weight = newValue;
}

Never mind that I’m simplifying things a bit here, because the actual code inside the curly brackets isn’t relevant to the discussion. I want to stress the fact that the compiler actually inserts standard Objective-C accessor methods, -weight and -setWeight:; that is, the methods exist in the compiled binary and to the outside world they look just like any other Objective-C methods. If you had to implement this property yourself, you would write these accessor methods too.

Remember when I said that a property is not the same thing as an instance variable? Here’s an example:

Getter Accessor Method with Unit Conversion
1
2
3
4
5
6
7
8
9
- (float) weight
{
    return _weight * 28.35f;
}

- (void) setWeight: (float) newValue
{
    _weight = newValue / 28.35f;
}

Aha! So the instance variable keeps the weight in ounces (this is called an implementation detail) and the getter accessor method returns the weight in grams. When you use the weight property, you get the weight in grams too. Note that without access to the source code you would not even suspect that the class uses other measurement units internally, because it takes and returns grams. This is called encapsulation in object-oriented programming: you only see what you need to see, poking around in other people’s objects is frown upon and may have consequences.

What does it matter to you? Whether you write myBag.weight or [myBag weight] – or myBag.weight = 2000.0f or [myBag setWeight: 2000.0f] – the code that is going to be executed is the same. The difference is entirely syntactic, which brings us to the question of style and importance of syntax.

The Value of Style

Coding style is not about writing code that works, it’s about writing readable code. Remember, you don’t write code for a compiler, you write it for humans, including yourself. Perhaps, in half a year – when you can’t remember every subtle detail – you will have to fix a bug in your own program. You will read your own code, asking yourself, what the heck the geek who wrote it was thinking. It’s better to spend time writing readable code now than to waste time deciphering a mess later.

Please, don’t write code like this unless you’re trying to win The International Obfuscated C Code Contest:

1
double l;main(_,o,O){return putchar((_--+22&&_+44&&main(_,-43,_),_&&o)?(main(-43,++o,O),((l=(o+21)/sqrt(3-O*22-O*O),l*l<4&&(fabs(((time(0)-607728)%2551443)/405859.-4.7+acos(l/2))<1.57))[" #"])):10);}

Dot Notation Misuse

From the compiler’s point of view, it’s perfectly valid to use the dot notation and the traditional Objective-C message syntax interchangeably:

1
2
3
NSArray *myArray = ...;
if ([myArray count] != myArray.count)
    NSLog(@"The compiler has gone crazy");

Luckily for us, a human brain is orders of magnitude more intelligent than any compiler humans have created so far. Here’s the problem: when a trained eye of an experienced Objective-C developer sees a dot following an object, it sends a signal to other brain convolutions that the dot is followed by a property. Then it goes like this, “Wait, I recognize the thing; count is not actually a property, it’s just an accessor method. The syntax is OK, though. Ignored. Proceed.”

I contend that, having saved exactly two key strokes once, you make a reader spend more mental effort every time somebody reads the code. It’s not that bad in cases when the method name is well-known, but if a reader doesn’t recognize the method immediately, it may cause confusion.

Let’s now consider more egregious examples.

1
double currentThreadPriority = NSThread.threadPriority;

You know what? Class objects don’t have properties, period. This will stall the parsing pipeline in any brain. Don’t do it.

1
2
NSFileHandle *fileHandle = ...;
NSData *data = fileHandle.readDataToEndOfFile;

How can a verb be a property? WTF? It’s an Objective-C method, not a C++ member function or other irrelevant shit like that. Have some respect for the language!

I cringe at the syntax misuse. It compiles and works, sure, but it looks weird, as if written by aliens. It demonstrates that you either don’t understand the language or don’t care about your work. If you do care, take some time to read “The Objective-C Programming Language” and “Concepts in Objective-C Programming”, the guides available right under the Documentation tab in the Xcode Organizer (⌘⇧2, Cmd+Shift+2). When done, welcome to Stack Overflow.

Comments