Clang 3.1 and Apple's LLVM 4.0 introduced new literal syntax for object creation and collection indexing in Objective-C, allowing simpler use of NSNumber, NSArray and NSDictionary. Use this tag for questions regarding that syntax.
Objective-C has always had compiler support for creation of object instances from literal character strings, just as C allows creation of a char *
from a literal string. In Cocoa programming (and other frameworks that derive from or imitate NeXTSTEP'S frameworks), the construct @"Lemon curry?"
in source code creates an NSString
instance.
Clang 3.1 and Apple's LLVM 4.0 compiler introduced support for other literal objects, expanding the use of the @
character to denote object creation from what would otherwise appear to be primitives. The new syntax allows creation of NSNumber
s, NSArray
s, and NSDictionary
s, as well as "boxing" of scalar expressions (such as enum
s and BOOL
s).
For (contrived) example,
@[ @{ @3 : @(NSCaseInsensitiveSearch) }, @{ @"With a melon?" : @(YES) } ];
creates an NSArray
containing two NSDictionary
s, the first of which has a key/value pair of an NSNumber
whose value is 3 and an NSNumber
whose value is the numerical value of NSCaseInsensitiveSearch
. The second dictionary has a pair whose key is a string and whose value is a boxed BOOL
, which also becomes an NSNumber
object.
Previous to the introduction of this syntax, the creation of these objects would have been much more unwieldy:
[NSArray arrayWithObjects:[NSDictionary dictionaryWithObject:[NSNumber numberWithUnsignedInteger:NSCaseInsensitiveSearch]
forKey:[NSNumber numberWithInt:3]],
[NSDictionary dictionaryWithObject:@"With a melon?"
forKey:[NSNumber numberWithBool:YES]], nil];
There is an important distinction, although an implementation detail, between literal strings and this new literal support. @"Lemon curry"
is an instance of __NSCFConstantString
, a private subclass of NSString
, which is created at compile-time, and whose contents are stored in the DATA segment of the program's binary. By contrast, the literal syntax for other objects is rewritten by the compiler into constructor method calls -- these objects are created at runtime, just as any other instance of their classes would be. (For this reason, literals other than NSString
s cannot be used to initialize a static or global variable.)
Associated indexing syntax for dictionaries and arrays was also added. Starting from the array created above,
NSDictionary * d = theArray[1];
NSNumber * n = d[@"With a melon?"];
results in n
holding an NSNumber
representing the boolean value YES
. It should be noted that this indexing feature requires framework support which is not present in SDKs pre-iOS 6 or OS X 10.8. (The compiler does not rewrite the subscript operation into objectAtIndex:
and objectForKey:
, but objectAtIndexedSubscript:
, and objectForKeyedSubscript:
which do not exist in earlier versions of Foundation.)
Such support can be added fairly easily, however. See Is there any way to get the neat Objective-C literal indexing feature in Xcode 4.4? or Aaron Hayman's answer to Compiler error "expected method not found" when using subscript on NSArray
Full details of this syntax can be found at the Clang website: https://clang.llvm.org/docs/ObjectiveCLiterals.html