- New Literals / Numbers / Boxings
- Container Literals / Subscripting / Feature Tests
Container Literals
Container literals introduce another great language feature. Until now, you've had to create dictionaries and arrays along the following lines. This snippet creates a three item array and a three-key dictionary.
NSArray *array = [NSArray arrayWithObjects: @"one", @"two", @"three", nil]; NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: @"a", @"one", @"b", @"two", @"c", @"three", nil];
These forms are wordy and require a nil terminator. That's not always a bad thing, but certainly a thing that's easy to forget and one that's bitten nearly every developer at some point along the line. What's more, the dictionary declaration requires value followed by key. That's the opposite of how most people conceptualize and express dictionary entries, even though the method name indicates the proper order.
Container literals address both concerns by introducing a new, simpler syntax. Here are examples of how you'll be able to declare an array and a dictionary.
NSArray *array = @[@"one", @"two", @"three"]; NSDictionary *dict = @{ @"one":@"a", @"two":@"b", @"three":@"c" };
Arrays consist of square brackets with a comma-delimited list of items. Dictionaries are formed with a curly braced list, where comma-delimited key-value pairs are associated by colons. In neither case do you need to add a nil terminator. Notice that the key/value ordering has switched to what I consider a far more sensible key-then-value definition versus the older object-then-key layout.
When evaluated, these expressions produce the same results as the previous two assignments declared with the traditional approach. The standard container rules still apply. (Don't add keys or values that evaluate to nil. Make sure that each item is typed as an object pointer. Conform to <NSCopying>.)
Subscripting
Clang introduces container access using standard subscripting, via square brackets. In other words, you can now access an NSArray just like you would a C array. You can do the same with an NSDictionary, although indexed by key rather than number. Here are a couple of examples of doing so, using the array and dictionary declared above.
NSLog(@"%@", array[1]); // @"two" NSLog(@"%@", dictionary[@"two"]); // @"b"
But you're not just limited to value look-ups. Using this new syntax, you can perform assignments as well for mutable instances. Here's how you might use the new subscripting features in simple assignments:
mutableArray[0] = @"first!"; mutableDictionary[@"some key"] = @"new value";
You still have to watch out for the index. Reading and writing an index outside the array range raises an exception.
Best of all, you can extend this subscripted behavior to custom classes by implementing support for a few core methods. So if you want an element of a custom class to offer indexed access, you can provide that support by implementing one or more of the following methods:
objectAtIndexedSubscript: anIndex setObject: newValue atIndexedSubscript: anIndex objectForKeyedSubscript: aKey setObject: newValue forKeyedSubscript: aKey
You chose whether you want access by order (array-style index) and/or keyword (dictionary-style key) and whether that access can update values (mutable-style). Simply implement the methods you wish to support and let the compiler handle the rest for you.
Feature Tests
As a final note, be aware that you can create feature-dependent coding. Just use clang's __has_feature test to see whether literals are available in the current compiler. Feature tests include array literals (objc_array_literals), dictionary literals (objc_dictionary_literals), object subscripting (objc_subscripting), numeric literals (objc_bool), and boxed expressions (objc_boxed_expressions).
#if __has_feature(objc_array_literals) // ... #else // ... #endif
Conclusion
Last year, Apple introduced ARC support, a compiler feature that provides automatic reference counting. It was a huge change and I quickly grew to love it. I could not be more delighted this year to see Objective-C literals arrive to the developer table. Even if Apple offers no other language re-imagination at this years WWDC developer's conference, I will rest happy that such a lovely and thoughtful step forward has been added into our coding arsenal. These features may seem simple and easy-to-overlook, but I predict they will greatly impact how we code on a daily basis.
Thanks, Jeremy Tregunna, Remy "Psy" Demerest, and everyone else who helped read and comment on this write-up in advance. All the good bits are theirs. All the mistakes are mine.