¿Cuáles son los detalles de "Objective-C Literals" mencionados en las notas de lanzamiento de Xcode 4.4?

188

Estaba revisando las notas de la versión de Xcode 4.4 y noté esto:

Compilador LLVM 4.0

Xcode ahora incluye el compilador Apple LLVM versión 4.0, que incluye las siguientes características nuevas del lenguaje Objective-C: [...]
- Literales Objective-C: crea literales para NSArray, NSDictionary y NSNumber, igual que los literales para NSString

Estoy intrigado por esta característica. No está del todo claro para mí sólo cómo literales de NSStringtrabajo y cómo se podría utilizar en NSArray, NSDictionaryy NSNumber.

¿Cuáles son los detalles?

Pedro Mancheno
fuente
No es una respuesta, pero hay algunas especulaciones aquí: reddit.com/r/programming/comments/pso6x/xcode_43_released/…
Arjan Tijms
3
"¿No está este material sujeto a una NDA?" ¿Y tu problema es?
Hejazzman
77
No, Apple ha dicho explícitamente que estas adiciones no son NDA en la lista de correo.
griotspeak
2
LLVM tiene algunos documentos sobre esto: clang.llvm.org/docs/LanguageExtensions.html#objc_lambdas
Steven Kramer
3
Aquí hay un enlace directo a la discusión en Clang de los literales de Objective-C: clang.llvm.org/docs/ObjectiveCLiterals.html
ThomasW

Respuestas:

393

Copiado textualmente de http://cocoaheads.tumblr.com/post/17757846453/objective-c-literals-for-nsdictionary-nsarray-and :

Literales de Objective-C: ahora se pueden crear literales para NSArray, NSDictionary y NSNumber (al igual que se pueden crear literales para NSString)

NSArray Literals

Previamente:

array = [NSArray arrayWithObjects:a, b, c, nil];

Ahora:

array = @[ a, b, c ];

NSDictionary Literals

Previamente:

dict = [NSDictionary dictionaryWithObjects:@[o1, o2, o3]
                                   forKeys:@[k1, k2, k3]];

Ahora:

dict = @{ k1 : o1, k2 : o2, k3 : o3 };

NSNumber Literals

Previamente:

NSNumber *number;
number = [NSNumber numberWithChar:'X'];
number = [NSNumber numberWithInt:12345];
number = [NSNumber numberWithUnsignedLong:12345ul];
number = [NSNumber numberWithLongLong:12345ll];
number = [NSNumber numberWithFloat:123.45f];
number = [NSNumber numberWithDouble:123.45];
number = [NSNumber numberWithBool:YES];

Ahora:

NSNumber *number;
number = @'X';
number = @12345;
number = @12345ul;
number = @12345ll;
number = @123.45f;
number = @123.45;
number = @YES;

[Editar]

zxoq en http://news.ycombinator.com/item?id=3672744 ha agregado nuevas suscripciones más interesantes. (Agregado con literales):

arr[1]      === [arr objectAtIndex:1]
dict[@"key"] === [dict objectForKey:@"key"]

[Editar 2]

Los nuevos literales de ObjC se discutieron en varias sesiones de WWDC 2012 . Intencionalmente no eliminé los nombres de archivo y el tiempo de cada diapositiva para que pueda encontrarlos usted mismo si lo desea. Son esencialmente lo mismo que se indica en esta publicación, pero también hay algunas cosas nuevas que mencionaré arriba de las imágenes.

Tenga en cuenta que las imágenes son todas grandes. Simplemente arrástrelos a otra pestaña para verlos en su tamaño original

Literales y boxeo

[NSNumber numberWithint:42]
[NSNumber numberWithDouble:10.8]
[NSNumber numberWithBool:YES]
[NSNumber numberWithint:6 + x * 2012]

Literales y boxeo

@42
@10.8
@YES
@(6 + x * 2012)

Suscripción de colecciones

[NSArray arrayWithObjects: a, b, c, nil]
[array objectAtIndex:i]
[NSDictionary dictionaryWithObjectsAndKeys: v1, k1, v2, k2, nil];
[dictionary valueForKey:k]

Suscripción de colecciones

@[a, b, c]
array[i]
@{k1:v1, k2:v2}
dictionary[k]

@ # números, @ {} diccionarios, @ "" cadenas, @ [] matrices, @ () expresiones


Esta parte es nueva. Literales de expresión

Cuando tienes una expresión ( M_PI / 16por ejemplo) debes ponerla entre paréntesis.

¡Esta sintaxis funciona para expresiones numéricas, booleanos, encontrar un índice en una cadena (C-), valores booleanos, constantes de enumeración e incluso cadenas de caracteres!

Literales de expresión

NSNumber *piOverSixteen = [NSNumber numberWithDouble: (M_PI / 16)];

NSNumber *hexDigit = [NSNumber numberWithChar:"0123456789ABCDEF"[i % 16]];

NSNumber *usesScreenFonts = [NSNumber numberWithBool:[NSLayoutManager usesScreenFonts]];

NSNumber *writingDirection = [NSNumber numberWithInt:NSWritingDirectionLeftToRight];

NSNumber *path = [NSString stringWithUTF8String: getenv("PATH")];

Literales de expresión

NSNumber *piOverSixteen = @( M_PI / 16 );

NSNumber *hexDigit = @( "0123456789ABCDEF"[i % 16] );

NSNumber *usesScreenFonts = @( [NSLayoutManager usesScreenFonts] );

NSNumber *writingDirection = @( NSWritingDirectionLeftToRight );

NSNumber *path = @( getenv("PATH") );

Más información sobre las cadenas de caracteres y cómo / cuándo puede usar esta sintaxis literal:

Expresiones de cadena en caja

NSString *path = [NSString stringWithUTF8String: getenv("PATH")];
for (NSString *dir in [path componentsSeparatedByString: @":"]) {
    // search for a file in dir...
}

Expresiones de cadena en caja

NSString *path = @( getenv("PATH") );
for (NSString *dir in [path componentsSeparatedByString: @":"]) {
    // search for a file in dir...
}

Cómo funcionan los literales de matriz

Cómo funcionan los literales de matriz

// when you write this:
array = @[a, b, c ];

// compiler generates:
id objects[] = { a, b, c };
NSUInteger count = sizeof(objects) / sizeof(id);
array = [NSArray arrayWithObjects:objects count:count];

Cómo funcionan los literales del diccionario

Cómo funcionan los literales del diccionario

// when you write this:
dict = @{k1 : o1, k2 : o2, k3 : o3 };

// compiler generates:
id objects[] = { o1, o2, o3 };
id keys[] = { k1, k2, k3 };
NSUInteger count = sizeof(objects) / sizeof(id);
dict = [NSDictionary dictionaryWithObjects:objects
                                   forKeys:keys
                                     count:count];

Más información sobre la suscripción de matrices

Subscripting de matriz

@implementation SongList {
    NSMutableArray *_songs;
}

- (Song *)replaceSong:(Song *)newSong atindex:(NSUinteger)idx {
    Song *oldSong = [_songs objectAtIndex:idx];
    [_songs replaceObjectAtindex:idx withObject:newSong];
    return oldSong;
}

Subscripting de matriz

@implementation SongList {
    NSMutableArray *_songs;
}

- (Song *)replaceSong:(Song *)newSong atindex:(NSUinteger)idx {
    Song *oldSong = _songs[idx];
    _songs[idx] = newSong;
    return oldSong;
}    

Más información sobre la suscripción de diccionario

Suscripción de diccionario

@implementation Database {
    NSMutableDictionary *_storage;
}

- (id)replaceObject:(id)newObject forKey:(id <NSCopying>)key {
    id oldObject = [_storage objectForKey:key];
    [_storage setObject:object forKey:key];
    return oldObject;
}

Suscripción de diccionario

@implementation Database {
    NSMutableDictionary *_storage;
}

- (id)replaceObject:(id)newObject forKey:(id <NSCopying>)key {
    id oldObject = _storage[key];
    _storage[key] = newObject;
    return oldObject;
}

[Editar 3]

Mike Ash tiene una gran crítica sobre estos nuevos literales. Si quieres saber más sobre estas cosas, asegúrate de echarle un vistazo .


Pooria Azimi
fuente
9
¡Puedo ver esto acelerando mi codificación!
Pedro Mancheno
12
¿Hay alguna forma de obtener xCode 4.3 para admitir estas nuevas notaciones? Los quiero - EMPRESA ... pero estoy SO no "subir a la montaña" para ellos ...
Alex Grey
20
Tiene mucho contenido textual incrustado en imágenes aquí que un motor de búsqueda podría encontrar más fácilmente si se publicara como texto sin formato.
Bill the Lizard
55
@BilltheLizard Estoy respetuosamente en desacuerdo. La mayor parte de la prueba es o cosas un-investigable gusta {y [, o son palabras genéricas como array, idy @implementation. Las palabras clave relevantes son literal, objcy xcode, no las menciones específicas de [o @implementation. No desea que esta pregunta se muestre para consultas generales de ObjC en Google, solo debe mostrarse cuando alguien realiza una consulta objc literal, lo que sucede en la actualidad (gracias al título y las etiquetas).
Pooria Azimi
44
Ahora eso se llama una respuesta StackOverflow. Buen trabajo Pooria.
Nitish
15

El compilador de Objective-C tiene un conocimiento codificado del diseño de memoria de las instancias de la NSConstantStringclase, también conocida como la __CFConstantStringclase. Echa un vistazo a la RewriteObjCStringLiteralfunción lib/Rewrite/RewriteModernObjC.cppen el código fuente clang. El compilador simplemente emite datos que coinciden con el diseño de las instancias de la NSConstantStringclase.

Hay un par de posibilidades para literales NSArraye NSDictionaryinstancias. Podrían hacer algo como lo que hicieron para las cadenas literales: codificar el diseño de la instancia (para una subclase especial) en el compilador y emitir datos en ese diseño. O podrían hacer que el compilador emita un código que simplemente crea una instancia en tiempo de ejecución.

Rob Mayoff
fuente
2
La implementación de la sintaxis literal del objeto para NSArrayy NSDictionaryes bastante diferente a la de NSString. El compilador simplemente genera una llamada NSDictionaryo NSArrayen tiempo de ejecución. Esta es también la razón por la cual las variables globales no pueden inicializarse usando esta sintaxis (a diferencia de NSString). Esto requeriría que el resultado sea una constante de tiempo de compilación.
Buzzy
1

De "Objective-C Literals"

1) NSNumber, NSDictionaryy los NSArrayliterales están disponibles en Xcode 4.4 .

2) NSDictionaryy la NSArraysuscripción requiere " Xcode 4.4 y OS X 10.8 o posterior SDK " o " Xcode 4.5 y iOS 6 o posterior SDK "

Me parece que la suscripción requiere soporte de tiempo de ejecución y, por lo tanto, no funcionará antes de iOS6 .

Andz
fuente
en el mismo artículo dice "Implementa de nuevo a iOS 4" en la columna '
Implementación de
1
Accidentalmente usé literales de matriz en un proyecto que compilé con Xcode 4.5. Funciona bien en un iPad con iOS5. No se compila en Xcode 4.2, que es cómo descubrí que lo hice.
JScarry
Se puede hacer que la suscripción funcione con Xcode 4.4 y el SDK de iOS5 que se incluye si agrega un encabezado: github.com/tewha/iOS-Subscripting/blob/master/…
Steven Fisher