blob: 9fe7f66dffbf3bd69e513b336dedbff6c57a93e0 [file] [log] [blame]
Sean Silva426914a2012-12-21 00:17:02 +00001====================
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
Richard Trieuc158c5a2014-01-25 01:32:39 +000094``<objc/objc.h>``:
Sean Silva426914a2012-12-21 00:17:02 +000095
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
Alex Denisovfde64952015-06-26 05:28:36 +0000122Expressions of scalar (numeric, enumerated, BOOL), C string pointer
123and some C structures (via NSValue) are supported:
Sean Silva426914a2012-12-21 00:17:02 +0000124
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
Alex Denisov21065ec2015-06-27 19:04:55 +0000139 // structs.
140 NSValue *center = @(view.center); // Point p = view.center;
Alex Denisovfde64952015-06-26 05:28:36 +0000141 // [NSValue valueWithBytes:&p objCType:@encode(Point)];
142 NSValue *frame = @(view.frame); // Rect r = view.frame;
143 // [NSValue valueWithBytes:&r objCType:@encode(Rect)];
144
Sean Silva426914a2012-12-21 00:17:02 +0000145Boxed 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
Sean Silva173d2522013-01-02 13:07:47 +0000173:ref:`fixed underlying type <objc-fixed-enum>` as in:
Sean Silva426914a2012-12-21 00:17:02 +0000174
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
Sean Silva173d2522013-01-02 13:07:47 +0000185be a :ref:`fixed underlying type <objc-fixed-enum>`
Sean Silva426914a2012-12-21 00:17:02 +0000186or 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
Alex Denisovfde64952015-06-26 05:28:36 +0000227Boxed 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
Sean Silva426914a2012-12-21 00:17:02 +0000263Container 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
Richard Trieuc158c5a2014-01-25 01:32:39 +0000296``<NSCopying>`` protocol.
Sean Silva426914a2012-12-21 00:17:02 +0000297
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
Alex Denisovfde64952015-06-26 05:28:36 +0000584 #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
Sean Silva426914a2012-12-21 00:17:02 +0000600Code 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.