1==================== 2Objective-C Literals 3==================== 4 5Introduction 6============ 7 8Three new features were introduced into clang at the same time: 9*NSNumber Literals* provide a syntax for creating ``NSNumber`` from 10scalar literal expressions; *Collection Literals* provide a short-hand 11for creating arrays and dictionaries; *Object Subscripting* provides a 12way to use subscripting with Objective-C objects. Users of Apple 13compiler releases can use these features starting with the Apple LLVM 14Compiler 4.0. Users of open-source LLVM.org compiler releases can use 15these features starting with clang v3.1. 16 17These language additions simplify common Objective-C programming 18patterns, make programs more concise, and improve the safety of 19container creation. 20 21This document describes how the features are implemented in clang, and 22how to use them in your own programs. 23 24NSNumber Literals 25================= 26 27The framework class ``NSNumber`` is used to wrap scalar values inside 28objects: signed and unsigned integers (``char``, ``short``, ``int``, 29``long``, ``long long``), floating point numbers (``float``, 30``double``), and boolean values (``BOOL``, C++ ``bool``). Scalar values 31wrapped in objects are also known as *boxed* values. 32 33In Objective-C, any character, numeric or boolean literal prefixed with 34the ``'@'`` character will evaluate to a pointer to an ``NSNumber`` 35object initialized with that value. C's type suffixes may be used to 36control the size of numeric literals. 37 38Examples 39-------- 40 41The following program illustrates the rules for ``NSNumber`` literals: 42 43.. code-block:: objc 44 45 void main(int argc, const char *argv[]) { 46 // character literals. 47 NSNumber *theLetterZ = @'Z'; // equivalent to [NSNumber numberWithChar:'Z'] 48 49 // integral literals. 50 NSNumber *fortyTwo = @42; // equivalent to [NSNumber numberWithInt:42] 51 NSNumber *fortyTwoUnsigned = @42U; // equivalent to [NSNumber numberWithUnsignedInt:42U] 52 NSNumber *fortyTwoLong = @42L; // equivalent to [NSNumber numberWithLong:42L] 53 NSNumber *fortyTwoLongLong = @42LL; // equivalent to [NSNumber numberWithLongLong:42LL] 54 55 // floating point literals. 56 NSNumber *piFloat = @3.141592654F; // equivalent to [NSNumber numberWithFloat:3.141592654F] 57 NSNumber *piDouble = @3.1415926535; // equivalent to [NSNumber numberWithDouble:3.1415926535] 58 59 // BOOL literals. 60 NSNumber *yesNumber = @YES; // equivalent to [NSNumber numberWithBool:YES] 61 NSNumber *noNumber = @NO; // equivalent to [NSNumber numberWithBool:NO] 62 63 #ifdef __cplusplus 64 NSNumber *trueNumber = @true; // equivalent to [NSNumber numberWithBool:(BOOL)true] 65 NSNumber *falseNumber = @false; // equivalent to [NSNumber numberWithBool:(BOOL)false] 66 #endif 67 } 68 69Discussion 70---------- 71 72NSNumber literals only support literal scalar values after the ``'@'``. 73Consequently, ``@INT_MAX`` works, but ``@INT_MIN`` does not, because 74they are defined like this: 75 76.. code-block:: objc 77 78 #define INT_MAX 2147483647 /* max value for an int */ 79 #define INT_MIN (-2147483647-1) /* min value for an int */ 80 81The definition of ``INT_MIN`` is not a simple literal, but a 82parenthesized expression. Parenthesized expressions are supported using 83the `boxed expression <#objc_boxed_expressions>`_ syntax, which is 84described in the next section. 85 86Because ``NSNumber`` does not currently support wrapping ``long double`` 87values, the use of a ``long double NSNumber`` literal (e.g. 88``@123.23L``) will be rejected by the compiler. 89 90Previously, the ``BOOL`` type was simply a typedef for ``signed char``, 91and ``YES`` and ``NO`` were macros that expand to ``(BOOL)1`` and 92``(BOOL)0`` respectively. To support ``@YES`` and ``@NO`` expressions, 93these macros are now defined using new language keywords in 94``<objc/objc.h>``: 95 96.. code-block:: objc 97 98 #if __has_feature(objc_bool) 99 #define YES __objc_yes 100 #define NO __objc_no 101 #else 102 #define YES ((BOOL)1) 103 #define NO ((BOOL)0) 104 #endif 105 106The compiler implicitly converts ``__objc_yes`` and ``__objc_no`` to 107``(BOOL)1`` and ``(BOOL)0``. The keywords are used to disambiguate 108``BOOL`` and integer literals. 109 110Objective-C++ also supports ``@true`` and ``@false`` expressions, which 111are equivalent to ``@YES`` and ``@NO``. 112 113Boxed Expressions 114================= 115 116Objective-C provides a new syntax for boxing C expressions: 117 118.. code-block:: objc 119 120 @( <expression> ) 121 122Expressions of scalar (numeric, enumerated, BOOL), C string pointer 123and some C structures (via NSValue) are supported: 124 125.. code-block:: objc 126 127 // numbers. 128 NSNumber *smallestInt = @(-INT_MAX - 1); // [NSNumber numberWithInt:(-INT_MAX - 1)] 129 NSNumber *piOverTwo = @(M_PI / 2); // [NSNumber numberWithDouble:(M_PI / 2)] 130 131 // enumerated types. 132 typedef enum { Red, Green, Blue } Color; 133 NSNumber *favoriteColor = @(Green); // [NSNumber numberWithInt:((int)Green)] 134 135 // strings. 136 NSString *path = @(getenv("PATH")); // [NSString stringWithUTF8String:(getenv("PATH"))] 137 NSArray *pathComponents = [path componentsSeparatedByString:@":"]; 138 139 // structs. 140 NSValue *center = @(view.center); // Point p = view.center; 141 // [NSValue valueWithBytes:&p objCType:@encode(Point)]; 142 NSValue *frame = @(view.frame); // Rect r = view.frame; 143 // [NSValue valueWithBytes:&r objCType:@encode(Rect)]; 144 145Boxed Enums 146----------- 147 148Cocoa frameworks frequently define constant values using *enums.* 149Although enum values are integral, they may not be used directly as 150boxed literals (this avoids conflicts with future ``'@'``-prefixed 151Objective-C keywords). Instead, an enum value must be placed inside a 152boxed expression. The following example demonstrates configuring an 153``AVAudioRecorder`` using a dictionary that contains a boxed enumeration 154value: 155 156.. code-block:: objc 157 158 enum { 159 AVAudioQualityMin = 0, 160 AVAudioQualityLow = 0x20, 161 AVAudioQualityMedium = 0x40, 162 AVAudioQualityHigh = 0x60, 163 AVAudioQualityMax = 0x7F 164 }; 165 166 - (AVAudioRecorder *)recordToFile:(NSURL *)fileURL { 167 NSDictionary *settings = @{ AVEncoderAudioQualityKey : @(AVAudioQualityMax) }; 168 return [[AVAudioRecorder alloc] initWithURL:fileURL settings:settings error:NULL]; 169 } 170 171The expression ``@(AVAudioQualityMax)`` converts ``AVAudioQualityMax`` 172to an integer type, and boxes the value accordingly. If the enum has a 173:ref:`fixed underlying type <objc-fixed-enum>` as in: 174 175.. code-block:: objc 176 177 typedef enum : unsigned char { Red, Green, Blue } Color; 178 NSNumber *red = @(Red), *green = @(Green), *blue = @(Blue); // => [NSNumber numberWithUnsignedChar:] 179 180then the fixed underlying type will be used to select the correct 181``NSNumber`` creation method. 182 183Boxing a value of enum type will result in a ``NSNumber`` pointer with a 184creation method according to the underlying type of the enum, which can 185be a :ref:`fixed underlying type <objc-fixed-enum>` 186or a compiler-defined integer type capable of representing the values of 187all the members of the enumeration: 188 189.. code-block:: objc 190 191 typedef enum : unsigned char { Red, Green, Blue } Color; 192 Color col = Red; 193 NSNumber *nsCol = @(col); // => [NSNumber numberWithUnsignedChar:] 194 195Boxed C Strings 196--------------- 197 198A C string literal prefixed by the ``'@'`` token denotes an ``NSString`` 199literal in the same way a numeric literal prefixed by the ``'@'`` token 200denotes an ``NSNumber`` literal. When the type of the parenthesized 201expression is ``(char *)`` or ``(const char *)``, the result of the 202boxed expression is a pointer to an ``NSString`` object containing 203equivalent character data, which is assumed to be '\\0'-terminated and 204UTF-8 encoded. The following example converts C-style command line 205arguments into ``NSString`` objects. 206 207.. code-block:: objc 208 209 // Partition command line arguments into positional and option arguments. 210 NSMutableArray *args = [NSMutableArray new]; 211 NSMutableDictionary *options = [NSMutableDictionary new]; 212 while (--argc) { 213 const char *arg = *++argv; 214 if (strncmp(arg, "--", 2) == 0) { 215 options[@(arg + 2)] = @(*++argv); // --key value 216 } else { 217 [args addObject:@(arg)]; // positional argument 218 } 219 } 220 221As with all C pointers, character pointer expressions can involve 222arbitrary pointer arithmetic, therefore programmers must ensure that the 223character data is valid. Passing ``NULL`` as the character pointer will 224raise an exception at runtime. When possible, the compiler will reject 225``NULL`` character pointers used in boxed expressions. 226 227Boxed C Structures 228------------------ 229 230Boxed expressions support construction of NSValue objects. 231It said that C structures can be used, the only requirement is: 232structure should be marked with ``objc_boxable`` attribute. 233To support older version of frameworks and/or third-party libraries 234you may need to add the attribute via ``typedef``. 235 236.. code-block:: objc 237 238 struct __attribute__((objc_boxable)) Point { 239 // ... 240 }; 241 242 typedef struct __attribute__((objc_boxable)) _Size { 243 // ... 244 } Size; 245 246 typedef struct _Rect { 247 // ... 248 } Rect; 249 250 struct Point p; 251 NSValue *point = @(p); // ok 252 Size s; 253 NSValue *size = @(s); // ok 254 255 Rect r; 256 NSValue *bad_rect = @(r); // error 257 258 typedef struct __attribute__((objc_boxable)) _Rect Rect; 259 260 NSValue *good_rect = @(r); // ok 261 262 263Container Literals 264================== 265 266Objective-C now supports a new expression syntax for creating immutable 267array and dictionary container objects. 268 269Examples 270-------- 271 272Immutable array expression: 273 274.. code-block:: objc 275 276 NSArray *array = @[ @"Hello", NSApp, [NSNumber numberWithInt:42] ]; 277 278This creates an ``NSArray`` with 3 elements. The comma-separated 279sub-expressions of an array literal can be any Objective-C object 280pointer typed expression. 281 282Immutable dictionary expression: 283 284.. code-block:: objc 285 286 NSDictionary *dictionary = @{ 287 @"name" : NSUserName(), 288 @"date" : [NSDate date], 289 @"processInfo" : [NSProcessInfo processInfo] 290 }; 291 292This creates an ``NSDictionary`` with 3 key/value pairs. Value 293sub-expressions of a dictionary literal must be Objective-C object 294pointer typed, as in array literals. Key sub-expressions must be of an 295Objective-C object pointer type that implements the 296``<NSCopying>`` protocol. 297 298Discussion 299---------- 300 301Neither keys nor values can have the value ``nil`` in containers. If the 302compiler can prove that a key or value is ``nil`` at compile time, then 303a warning will be emitted. Otherwise, a runtime error will occur. 304 305Using array and dictionary literals is safer than the variadic creation 306forms commonly in use today. Array literal expressions expand to calls 307to ``+[NSArray arrayWithObjects:count:]``, which validates that all 308objects are non-``nil``. The variadic form, 309``+[NSArray arrayWithObjects:]`` uses ``nil`` as an argument list 310terminator, which can lead to malformed array objects. Dictionary 311literals are similarly created with 312``+[NSDictionary dictionaryWithObjects:forKeys:count:]`` which validates 313all objects and keys, unlike 314``+[NSDictionary dictionaryWithObjectsAndKeys:]`` which also uses a 315``nil`` parameter as an argument list terminator. 316 317Object Subscripting 318=================== 319 320Objective-C object pointer values can now be used with C's subscripting 321operator. 322 323Examples 324-------- 325 326The following code demonstrates the use of object subscripting syntax 327with ``NSMutableArray`` and ``NSMutableDictionary`` objects: 328 329.. code-block:: objc 330 331 NSMutableArray *array = ...; 332 NSUInteger idx = ...; 333 id newObject = ...; 334 id oldObject = array[idx]; 335 array[idx] = newObject; // replace oldObject with newObject 336 337 NSMutableDictionary *dictionary = ...; 338 NSString *key = ...; 339 oldObject = dictionary[key]; 340 dictionary[key] = newObject; // replace oldObject with newObject 341 342The next section explains how subscripting expressions map to accessor 343methods. 344 345Subscripting Methods 346-------------------- 347 348Objective-C supports two kinds of subscript expressions: *array-style* 349subscript expressions use integer typed subscripts; *dictionary-style* 350subscript expressions use Objective-C object pointer typed subscripts. 351Each type of subscript expression is mapped to a message send using a 352predefined selector. The advantage of this design is flexibility: class 353designers are free to introduce subscripting by declaring methods or by 354adopting protocols. Moreover, because the method names are selected by 355the type of the subscript, an object can be subscripted using both array 356and dictionary styles. 357 358Array-Style Subscripting 359^^^^^^^^^^^^^^^^^^^^^^^^ 360 361When the subscript operand has an integral type, the expression is 362rewritten to use one of two different selectors, depending on whether 363the element is being read or written. When an expression reads an 364element using an integral index, as in the following example: 365 366.. code-block:: objc 367 368 NSUInteger idx = ...; 369 id value = object[idx]; 370 371it is translated into a call to ``objectAtIndexedSubscript:`` 372 373.. code-block:: objc 374 375 id value = [object objectAtIndexedSubscript:idx]; 376 377When an expression writes an element using an integral index: 378 379.. code-block:: objc 380 381 object[idx] = newValue; 382 383it is translated to a call to ``setObject:atIndexedSubscript:`` 384 385.. code-block:: objc 386 387 [object setObject:newValue atIndexedSubscript:idx]; 388 389These message sends are then type-checked and performed just like 390explicit message sends. The method used for objectAtIndexedSubscript: 391must be declared with an argument of integral type and a return value of 392some Objective-C object pointer type. The method used for 393setObject:atIndexedSubscript: must be declared with its first argument 394having some Objective-C pointer type and its second argument having 395integral type. 396 397The meaning of indexes is left up to the declaring class. The compiler 398will coerce the index to the appropriate argument type of the method it 399uses for type-checking. For an instance of ``NSArray``, reading an 400element using an index outside the range ``[0, array.count)`` will raise 401an exception. For an instance of ``NSMutableArray``, assigning to an 402element using an index within this range will replace that element, but 403assigning to an element using an index outside this range will raise an 404exception; no syntax is provided for inserting, appending, or removing 405elements for mutable arrays. 406 407A class need not declare both methods in order to take advantage of this 408language feature. For example, the class ``NSArray`` declares only 409``objectAtIndexedSubscript:``, so that assignments to elements will fail 410to type-check; moreover, its subclass ``NSMutableArray`` declares 411``setObject:atIndexedSubscript:``. 412 413Dictionary-Style Subscripting 414^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 415 416When the subscript operand has an Objective-C object pointer type, the 417expression is rewritten to use one of two different selectors, depending 418on whether the element is being read from or written to. When an 419expression reads an element using an Objective-C object pointer 420subscript operand, as in the following example: 421 422.. code-block:: objc 423 424 id key = ...; 425 id value = object[key]; 426 427it is translated into a call to the ``objectForKeyedSubscript:`` method: 428 429.. code-block:: objc 430 431 id value = [object objectForKeyedSubscript:key]; 432 433When an expression writes an element using an Objective-C object pointer 434subscript: 435 436.. code-block:: objc 437 438 object[key] = newValue; 439 440it is translated to a call to ``setObject:forKeyedSubscript:`` 441 442.. code-block:: objc 443 444 [object setObject:newValue forKeyedSubscript:key]; 445 446The behavior of ``setObject:forKeyedSubscript:`` is class-specific; but 447in general it should replace an existing value if one is already 448associated with a key, otherwise it should add a new value for the key. 449No syntax is provided for removing elements from mutable dictionaries. 450 451Discussion 452---------- 453 454An Objective-C subscript expression occurs when the base operand of the 455C subscript operator has an Objective-C object pointer type. Since this 456potentially collides with pointer arithmetic on the value, these 457expressions are only supported under the modern Objective-C runtime, 458which categorically forbids such arithmetic. 459 460Currently, only subscripts of integral or Objective-C object pointer 461type are supported. In C++, a class type can be used if it has a single 462conversion function to an integral or Objective-C pointer type, in which 463case that conversion is applied and analysis continues as appropriate. 464Otherwise, the expression is ill-formed. 465 466An Objective-C object subscript expression is always an l-value. If the 467expression appears on the left-hand side of a simple assignment operator 468(=), the element is written as described below. If the expression 469appears on the left-hand side of a compound assignment operator (e.g. 470+=), the program is ill-formed, because the result of reading an element 471is always an Objective-C object pointer and no binary operators are 472legal on such pointers. If the expression appears in any other position, 473the element is read as described below. It is an error to take the 474address of a subscript expression, or (in C++) to bind a reference to 475it. 476 477Programs can use object subscripting with Objective-C object pointers of 478type ``id``. Normal dynamic message send rules apply; the compiler must 479see *some* declaration of the subscripting methods, and will pick the 480declaration seen first. 481 482Caveats 483======= 484 485Objects created using the literal or boxed expression syntax are not 486guaranteed to be uniqued by the runtime, but nor are they guaranteed to 487be newly-allocated. As such, the result of performing direct comparisons 488against the location of an object literal (using ``==``, ``!=``, ``<``, 489``<=``, ``>``, or ``>=``) is not well-defined. This is usually a simple 490mistake in code that intended to call the ``isEqual:`` method (or the 491``compare:`` method). 492 493This caveat applies to compile-time string literals as well. 494Historically, string literals (using the ``@"..."`` syntax) have been 495uniqued across translation units during linking. This is an 496implementation detail of the compiler and should not be relied upon. If 497you are using such code, please use global string constants instead 498(``NSString * const MyConst = @"..."``) or use ``isEqual:``. 499 500Grammar Additions 501================= 502 503To support the new syntax described above, the Objective-C 504``@``-expression grammar has the following new productions: 505 506:: 507 508 objc-at-expression : '@' (string-literal | encode-literal | selector-literal | protocol-literal | object-literal) 509 ; 510 511 object-literal : ('+' | '-')? numeric-constant 512 | character-constant 513 | boolean-constant 514 | array-literal 515 | dictionary-literal 516 ; 517 518 boolean-constant : '__objc_yes' | '__objc_no' | 'true' | 'false' /* boolean keywords. */ 519 ; 520 521 array-literal : '[' assignment-expression-list ']' 522 ; 523 524 assignment-expression-list : assignment-expression (',' assignment-expression-list)? 525 | /* empty */ 526 ; 527 528 dictionary-literal : '{' key-value-list '}' 529 ; 530 531 key-value-list : key-value-pair (',' key-value-list)? 532 | /* empty */ 533 ; 534 535 key-value-pair : assignment-expression ':' assignment-expression 536 ; 537 538Note: ``@true`` and ``@false`` are only supported in Objective-C++. 539 540Availability Checks 541=================== 542 543Programs test for the new features by using clang's \_\_has\_feature 544checks. Here are examples of their use: 545 546.. code-block:: objc 547 548 #if __has_feature(objc_array_literals) 549 // new way. 550 NSArray *elements = @[ @"H", @"He", @"O", @"C" ]; 551 #else 552 // old way (equivalent). 553 id objects[] = { @"H", @"He", @"O", @"C" }; 554 NSArray *elements = [NSArray arrayWithObjects:objects count:4]; 555 #endif 556 557 #if __has_feature(objc_dictionary_literals) 558 // new way. 559 NSDictionary *masses = @{ @"H" : @1.0078, @"He" : @4.0026, @"O" : @15.9990, @"C" : @12.0096 }; 560 #else 561 // old way (equivalent). 562 id keys[] = { @"H", @"He", @"O", @"C" }; 563 id values[] = { [NSNumber numberWithDouble:1.0078], [NSNumber numberWithDouble:4.0026], 564 [NSNumber numberWithDouble:15.9990], [NSNumber numberWithDouble:12.0096] }; 565 NSDictionary *masses = [NSDictionary dictionaryWithObjects:objects forKeys:keys count:4]; 566 #endif 567 568 #if __has_feature(objc_subscripting) 569 NSUInteger i, count = elements.count; 570 for (i = 0; i < count; ++i) { 571 NSString *element = elements[i]; 572 NSNumber *mass = masses[element]; 573 NSLog(@"the mass of %@ is %@", element, mass); 574 } 575 #else 576 NSUInteger i, count = [elements count]; 577 for (i = 0; i < count; ++i) { 578 NSString *element = [elements objectAtIndex:i]; 579 NSNumber *mass = [masses objectForKey:element]; 580 NSLog(@"the mass of %@ is %@", element, mass); 581 } 582 #endif 583 584 #if __has_attribute(objc_boxable) 585 typedef struct __attribute__((objc_boxable)) _Rect Rect; 586 #endif 587 588 #if __has_feature(objc_boxed_nsvalue_expressions) 589 CABasicAnimation animation = [CABasicAnimation animationWithKeyPath:@"position"]; 590 animation.fromValue = @(layer.position); 591 animation.toValue = @(newPosition); 592 [layer addAnimation:animation forKey:@"move"]; 593 #else 594 CABasicAnimation animation = [CABasicAnimation animationWithKeyPath:@"position"]; 595 animation.fromValue = [NSValue valueWithCGPoint:layer.position]; 596 animation.toValue = [NSValue valueWithCGPoint:newPosition]; 597 [layer addAnimation:animation forKey:@"move"]; 598 #endif 599 600Code can use also ``__has_feature(objc_bool)`` to check for the 601availability of numeric literals support. This checks for the new 602``__objc_yes / __objc_no`` keywords, which enable the use of 603``@YES / @NO`` literals. 604 605To check whether boxed expressions are supported, use 606``__has_feature(objc_boxed_expressions)`` feature macro. 607