Objective-C Properties – Always or Public-Only Under ARC?

objective cprogramming practicesproperties

After reading an article humbly named "The Code Commandments: Best Practices for Objective-C Coding" by Robert McNally a little less than two years ago, I adopted the practice of using properties for pretty much every data member of my Objective-C classes (the 3rd commandment as of may 2012). McNally lists these reasons for doing so (my emphasis):

  1. Properties enforce access restrictions (such as readonly)
  2. Properties enforce memory management policy (strong, weak)
  3. Properties provide the opportunity to transparently implement custom setters and getters.
  4. Properties with custom setters or getters can be used to enforce a thread-safety strategy.
  5. Having a single way to access instance variables increases code readability.

I put most of my properties in private categories, so number 1 and 4 are usually not issues I run in to. Arguments 3 and 5 are more 'soft', and with the right tools and other consistencies they could become non-issues. So finally, to me the most influential of these arguments was number 2, memory management. I've been doing this ever since.

@property (nonatomic, strong) id object; // Properties became my friends.

For my last few projects I've switched to using ARC, which made me doubt whether creating properties for pretty much anything is still a good idea or maybe a little superfluous. ARC takes care of memory managing Objective-C objects for me, which for most strong members works fine if you just declare the ivars. The C-types you had to manually manage anyway, before and after ARC, and the weak properties are mostly public ones.

Of course I still use properties for anything that needs access from outside of the class, but those are mostly only a handful of properties, while most data members are listed as ivars under the implementation header

@implementation GTWeekViewController
{
    UILongPressGestureRecognizer *_pressRecognizer;
    GTPagingGestureRecognizer *_pagingRecognizer;
    UITapGestureRecognizer *_tapRecognizer;
}

As an experiment I've been doing this a bit more rigorously, and the move away from properties for everything has some nice positive side effects.

  1. Data member code requirements (@property/@synthesize) shrunk down to just the ivar declaration.
  2. Most of my self.something references cleaned up to just _something.
  3. It's easily distinguishable which data members are private (ivars) and which are public (properties).
  4. Lastly, it 'feels' more like this was the purpose Apple intended properties for, but that's subjective speculation.

On to the question: I'm slowly sliding towards the dark side, using less and less properties in favor of implementation-ivars. Can you provide me with a bit of reasoning for why I should stick to using properties for everything, or confirm my current train of thoughts as to why I should use more ivars and less properties only where needed? The most persuasive answer for either side will receive my mark.

EDIT: McNally weighs in on Twitter, saying: "I think my main reason for sticking with properties is: one way to do everything, that does everything (including KVC/KVO.)"

Best Answer

Can you provide me with a bit of reasoning for why I should stick to using properties for everything, or confirm my current train of thoughts as to why I should use more ivars and less properties only where needed?

Right now, I think it's fair to say that it's mostly a matter of style. As you say, the memory management benefit of properties is less important with ARC. On the other hand, the "benefits" of going back to direct ivar access aren't very compelling either:

  1. A @property declaration is quite similar to an ivar declaration. Avoiding the @synthesize directive doesn't seem like a big win -- we're not talking about a lot of code.

  2. The foo.something syntax is arguably a lot better than _something. Property access syntax is obviously designed to look like and work like C's dot syntax for accessing members of a structure. Being explicit about which object you're accessing (whether that's self or something else) is helpful. (Some people -- not me! -- advocate self->something for ivar access for this reason.) The leading underscore convention for ivars is fine, but it's not used consistently by all Objective-C code.

  3. Properties seem a better choice for accessing data stored in other objects of the same class (which is allowed under "private" access) and for access by subclasses (like C++'s "protected"). So the 'properties == public' idea is somewhat blurry.

  4. My sense is that properties were intended to simplify memory management and provide some other benefits. As you say, with the memory management benefit decreased, properties seem less compelling.

The path you've chosen -- going back to direct ivar access for internal data -- seems like a very reasonable choice and there's no obvious reason to change your course. But sticking to properties is also quite reasonable -- the drawbacks aren't significant, and there are some nice benefits like KVO compliance and a more consistent member access style.

Properties weren't the last step in the evolution of Objective-C, and I don't expect that ARC will be either. I don't have any specific information, but it seems like a good guess that additional features might be added at some point that make properties either more compelling or less so. We'll have to wait and see what happens.