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