¿Qué encontrarás en este post?
ToggleLiterales para NSString
Desde hace algún tiempo ya, siempre enseño en mis cursos de programación iPhone el uso de literales para las colecciones. Ahorran muchísimo trabajo y ya era hora que Objective-C se apuntase al siglo XX (aprovechando que algunos ya están en el XXI).
Los literales más conocidos son los de siempre, los de las NSStrings. No hace falta crear un NSString de la siguiente manera:
NSString *saludo = [[NSString alloc] initWithCString:"Hola Mundo" encoding: NSUTF8StringEncoding]; // Chúpate esa
(gracias sean dadas al Altísimo), sino que basta con un simple:
NSString *saludo = @"Hola Mundo";
Desgraciadamente, hasta hace bien poco, este era el único tipo que tenía una representación literal, lo que hacía que crear un NSArray o un NSDictionary fuese una prueba de paciencia. Afortunadamente, las últimas versiones del compilador (OJO, esto no es un cambio al lenguaje sino al compilador) aceptan literales para NSArray y NSDictionary.
Aun tenemos que agachar la cabeza con humildad ante los Javascripteros (sí, hijos míos, los Javascripteros), que tienen literales para los objetos en general, y por lo tanto no necesitan inicializadores como el común de los mortales; pero al menos podemos mirar a la cara a Pythonistas y Rubistas.
Literales para NSArray
// Creamos un NSArray de la forma estándar. // El nil final indica que hemos terminado de meter objetos NSArray *lista = [NSArray arrayWithObjects: @"uno", @"dos", nil]; // Mediante literales NSArray *lista = @[@"uno", @"dos"];
Es importante tener en cuenta que la representación literal crea la versión inmutable, es decir, NSArray. Si necesitas la mutable, tendrás que enviar el mensaje mutableCopy.
Literales para NSDictionary
Los diccionarios no iban a ser menos, y también tienen una representación literal que recuerda bastante la de Python:
// Estilo antiguo NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: @"Inception",@"Zimmer", @"Star Wars", @"Williams", nil]; // Nuevo Clave Valor NSDictionary *d = @{ @"Zimmer" : @"Inception", @"Williams" : @"Star Wars"};
Fijaos que en este caso, en la representación literal es al revés del método tradicional (primero la clave y luego el valor). Aquí también el literal devuelve la versión inmutable, y si queremos la mutable tendremos que enviar un mutableCopy.
Lamentablemente, estas son las únicas colecciones para las cuales hay, de momento, expresiones literales. NSSet, por ejemplo, se quedó con las ganas.
Boxing, o literales para números
Hasta aquí, esto ya debería ser conocido por todos, pero ¿y los números? ¿Tenemos que seguir haciendo esto para meterlos en una colección?
// Empaqueto un escalar dentro de un objeto // (NSNUmber) para poder meterlo en una colección [NSNumber numberWithInt:42];
A este empaquetado de un escalar dentro de un objeto, se le llama “boxing”. Por suerte, tampoco tenemos que hacer esto, y el compilador lo hará por nosotros con tan solo anteponer el símbolo mágico que abre todas las puertas en Objective-C: @.
Además, podemos poner un sufijo que indique el tipo exacto del número (en caso de que no sea evidente).
- F indica un float (por defecto supone que un decimal es un double).
- U indica que se trata de un entero sin signo
- L indica que es un long
- LL indica que se trata de un looooong (long long) 😉
NSNumber *pi = @3.1425926; // a double NSNumber *shortPi = @3.1416F; // a float NSNumber *yes = @YES; // a BOOL NSNumber *answer = @42U; // unsigned integer NSNumber *longInt = @111112222L;// a long NSNumber *veryLong = @111111111111LL; // a long long
Todo esto está muy bien y muy bonito, pero y si el número que quieres empaquetar ¿es el resultado de una expresión aritmética? No temas, joven padawan, pues esto también ha sido tenido en cuenta. Para eso basta con poner la expresión entre paréntesis y precedidos de… ¡@! 😉
// Con los dedos de las manos y los dedos de los pies, // los XXXX y la XXX, todo suma veintitrés: NSNumber *total = @(10+10+2+1);
El lado Oscuro: sintaxis de indexado
Los diseñadores de LLVM iban tan bien encaminados, pero tan bien encaminados con los literales, que al final tuvieron que cagarla… No contentos con la dádiva de los literales para Objective-C, dieron un paso más, y cayeron en una charca.
Resulta que ahora también puedes acceder a los elementos de una colección con una sintaxis similar a como accederías a un elemento de un array de C:
// Eramos pocos corchetes y parió la abuela NSArray *jedis = @[@"Windu", @"Luke", @"Yoda", @"Anakin", @"Obi Wan"]; NSString *viejoVerde = nil; // En vez de... viejoVerde = [jedis objectAtIndex:2]; // ahora también así viejoVerde = jedis[2];
Personalmente, me parece una pésima idea. Saltarse la sintaxis habitual de Objective-C para añadir los literales era aceptable por la enorme economía de texto y comodidad que nos aporta. Sin embargo, meter más corchetes en un leguaje que ya tiene bastantes, y encima con un significado completamente distinto, ya me parece de locos.
Expresiones Literales en Objective C para Colecciones y Escalares
Hemos tardado un poco en ponernos al día, pero al fin podemos crear colecciones como las personas normales.