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