New additions to Objective-C in Xcode 7 – Nullability

Xcode 7 brings you two new concepts for Objective-C – Generics and Nullability!

I’ll cover Generics in another blogpost later.
Oh, and nullability somewhat already came with Xcode 6.3, but that’s not covered here though.

If you like me sometimes find yourself writing Objective-C almost all day long, this post could brighten your day a bit.

Apple has introduced the nullability concept to Objective-C, basically to ease up the bridging between Swift and Objective-C. The good part is that you can use it when Xcode 7 hit’s the store, and it’s quite easy to start using. The bad part is stated below, and with some examples throughout the blogpost.

From Apple’s documentation, here’s how they describe it:

Nullability annotation. Lets you indicate in Objective-C source when to expect a value to be nil or non-nil, smoothing the use of Objective-C frameworks and modules from Swift code.

Let’s see if we can use it in our daily Objective-C life, leveraging the new syntax available in Xcode 7 beta.

I’ve seen quite a lot of defensive control statements in Objective-C-written apps, even though it’s legal to send “something” to a nil receiver. It could be something like:

- (void) operationsOnArray:(NSArray *)array {
    if (array) {
        // do somehing with the array

Wouldn’t it be nice to have the compiler warn you if, intentionally or not, you’re sending a nil parameter to a receiver which doesn’t allow null? Of course it would. Here’s the modified version:

- (void) operationsOnArray:(NSArray __nonnull *)array {
    // do somehing with the array

Of course, this doesn’t fix the situation if someone calls our method with nil, e.g if we add the array to a dictionary using a convenience initialiser (@{@"array" : array, ...}). One might even argue that you’re delaying the inevitable by adding the if control statement checking for nil – if the method received a nil, you shouldn’t even have called it in the first place, but that’s for another blog post another time.

Basically, if you try to call a method which includes the __nonnull keyword, the compiler should warn you, and hopefully you would listen to it.

However, don’t be fooled, consider the following popquiz:
What’s the output in the console from the following code snippet?

__nonnull NSMutableArray *array = nil;

[array addObject:@"foo"];
NSLog(@"%@", array == nil ? @"Yes" : @"No");
NSLog(@"%@", [array firstObject]);

Yes, the output is of course Yes and (null). It’s simple and completely legal, even though it might not have the side effects you expected. Not even the compiler is complaining! You should remember that it’s legal to send the addObject message to nil as an instance (although it’s not legal to send addObject with a nil parameter to an array).

The __nullable keyword is in place also, and can state the opposite intent of __nonnull.

To quickly summarise, __nullable and __nonnull is best thought of as stating an intent, nothing more. It’s not a bulletproof guard against nil, but it improves your possibility to state your intent and is in fact pretty much what Apple promises us: “Lets you indicate in Objective-C source when to expect a value to be nil or non-nil, smoothing the use of Objective-C frameworks and modules from Swift code.”. Remember this, and it’s not that bad.

At the moment of writing, I’ve only been able to produce a compiler warning when explicitly sending nil as parameter to a method containing the __nonnull keyword. If I add a nullable keyword to a property, and use it as a parameter to a method with a nonnull paramater signature, the compiler doesn’t warn me at all. Even when assigning nil to a local variable and assigning that to a nonnull property, I get nothing from the compiler. I hope this get’s changed. After all, there’s still a lot of legacy Objective-C code out there.

The solution you ask? Probably wait for the next beta or final release of Xcode 7, or convert to Swift :-)

A prettified version exists of the __nonnull keyword, which you can use if you use it as a prefix to the type in a method signature:

- (void) operationsOnArray:(nonnull NSArray *)array {
    // do somehing with the array

Personally, I’ll probably start using this variant, even though I’m used to be able to read the parameter type as the first thing in the parentheses. For an even more “magic” variant, there’s a C macro in which you can encapsulate alle the properties you like, and state if they’re nullable or not. My advice is to stay away from that – it’s lazy, and more prone to errors when you surpass a significant amount of properties.

This Post Has One Comment

Leave a Reply