Andrew Madsen

Follow @armadsen on Micro.blog.

Objective-C Class Properties

While looking through the release notes for Foundation in iOS 10/macOS 10.12 Sierra, I noticed an item under “Overall API Updates”

Use of class properties, in both Swift as well as Objective-C, latter using the new “@property (class)” declaration.

Xcode 8 ships with a new versions of Clang and LLVM (800.0.2.24.1, and 8.0.0 as of the first beta). The new version of Clang adds support for class properties in Objective-C. The feature is not yet fully documented anywhere that I can find1, so I did a little experimenting.

Let’s say you have a Car class and want newly created cars to have an optional, configurable default color. In Swift you can already do:

class Car {
    static var defaultColor: UIColor?
}

Previously, in Objective-C, you might have done this using:

@interface Car : NSObject
+ (UIColor *)defaultColor;
+ (UIColor *)setDefaultColor:(UIColor *)defaultColor;
@end

This has long been a fairly common approach, mirroring as it does the convention for instance property accessor methods. It is used in a number of places in the system frameworks on OS X and iOS.

With the new support for Objective-C class properties, you can now do the following:

@interface Car : NSObject
@property (class) UIColor *defaultColor
@end

Here the class specifier in the list of attributes for the @property means this will be a class property rather than an instance property.

It is important to note that unlike regular instance properties, Objective-C class properties can not be synthesized using @synthesize, nor are they automatically synthesized by the compiler. You are responsible for implementing accessor methods for them yourself. (You can also use an @dynamic for them to tell the compiler that accessor methods will be provided at runtime.) If you don’t provide methods for them, you’ll get a compiler warning, and @synthesize produces a compiler error:

Compiler warning/error

The implementation of the methods will depend on exactly what the class property does, but one common approach is to back them with a static variable:

static UIColor *_carDefaultColor = nil;

@implementation Car

+ (UIColor *)defaultColor { return _carDefaultColor; }
+ (void)setDefaultColor:(UIColor *)defaultColor { _carDefaultColor = defaultColor; }

@end

It seems a fair bet that this feature was added for better bridging into Swift, where class properties have always existed. Before real Objective-C class properties, you would have had to call the accessor methods using method/function syntax:

Car.setDefaultColor(.white())

Now, when an Objective-C class with a class property is bridged into Swift, you can use regular property syntax to access the class property:

Car.defaultColor = .white()

Of course, this feature provides a nice benefit even for pure Objective-C code, where you can now use dot-notation to access class properties:

Car.defaultColor = [UIColor whiteColor];

Presumably, in cases where it makes sense, Apple will be using the new Objective-C class properties in system API, improving bridging into Swift. It’s not clear if they will go back and update existing API to use the new syntax. So far, only NSGridView and allowsAutomaticWindowTabbing in NSWindow (both new APIs in 10.12) are using the new syntax, but that may change.

It’s nice to continue to see updates being made to Objective-C. As with last year’s addition of lightweight generics, etc., even if they’re being done primarily for bridging with Swift, they provide some nice improvements for all Objective-C programmers.


  1. It was discussed on the LLVM mailing list and bug tracker during development, of course. ↩︎