Objective-C以复杂的语法著称,事实上确实是这样.不过从Objective-C1.0开始,有一个非常简单的方式创建NSString对象,那就是"字符串字面量",其语法如下:
NSString *str = @"Objective-C is the best programming language";
当然不用这样的语法的话,就要用常见的alloc及init方法来分配并初始化NSString对象了.在新版的编译器中,也能用这种字面量语法来声明NSNumber, NSArray, NSDictionary类的实例.使用字面量语法(literal syntax)可以缩减源代码的长度,使其可读性提高.
字面数值
整数, 浮点数, 布尔值封入Objective-C对象中.这种情况下,可以使用NSNumber类.
一般做法:
NSNumber *num = [NSNumber numberWithInt:3];
字面量语法:
NSNumber *num = @1;
可以看到,字面量语法更为简洁.不过它的好处还远不止这些,能以NSNumber实例表示的所有数据类型都可以使用该语法,例如:
NSNumber *intNum = @3;
NSNumber *floatNum = @3.3f;
NSNumber *doubleNum = @3.33333;
NSNumber *boolNum = @YES;
NSNumber *charNum = @'a';
同时字面量语法也适用于表达式:
int a = 3;
float b = 3.33f;
NSNumber *expressionNum = @(a * b);
用字面量来表示数值十分有用,这样做可以使NSNumber更为简洁,以为其中只有数字,没有其他多余成分.
字面量数组
数组是常用的数据结构,通常创建一个数组的方法是:
NSArray *array = [NSArray arrayWithObjects:@"one", @"two", @"three"];
而使用字面量语法来创建则是:
NSArray *array = @[@"one", @"two", @"three"];
这种做法不仅简单,而且还有利于操作数组,数组最常见的操作就是通过某个下标取得对应的对象,如果不适用"字面量语法",通常的做法是:
NSString *string = [array objectAtIndex:0];
适用字面量语法的做法则是:
NSString *string = array[0];
这样的做法简单明了,更容易理解.也和其他语言中访问数组中的某个元素类似.
注意:
使用字面量语法创建数组时,若数组元素对象中有nil,则会抛出异常.因为字面量语法其实是一种"语法糖"(计算机语言中与另外一套语法等效但是开发者使用起来更加方便的语法,语法糖可以使程序的可读性提高,同时减少代码出错率).其效果等于先创建了一个数组,然后把方括号中的所有对象都加到这个数组中.
举个例子:
id object1 = /* ... */;
id object2 = /* ... */;
id object3 = /* ... */;
NSArray *arrayA = [NSArray arrayWithObjects:object1, object2, object3];
NSArray *arrayB = @[object1, object2, object3];
不妨思考一下:如果object1和object3都指向了有效的Objective-C对象,而object2是nil,会出现什么情况?如果采用字面量语法,创建arrayB时会抛出异常(attempt to insert nil object from arrayB[1]),arrayA虽然能创建成功,但是其中只有一个object1对象,原因很简单:arrayWithObjects:方法会依次处理每个参数,直到发现nil为止.
这个差别表明:使用字面量语法更为安全.抛出异常令程序终止,这比创建好数组发现数组中元素个数不对要好很多.想数组中插入nil通常说明程序有错,通过异常可以更快的找个这个错误.
字面量字典
"字典"是一种映射型数据结构,可向其中添加键值对.OC中通常创建字典的做法是:
NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:
@"Country" ,@"firstName",
@"Gene", @"lastName",
@[NSNumber numberWitnInt:18], @"age", nil];
这样写令代码的可读性不高,因为顺序是<对象>, <键>.这与通常的理解刚好相反.我们一般理解为"键"映射到"对象".然而使用字面量语法:
NSDictionary *dictionary = @{@"firstName" : @"Country",
@"lastName" : @"Gene"
@"age" : @18};
这样写的好处一目了然.代码可读性还高.同时还指明:字典中的对象和建都必须是OC对象,所以不能把18直接放到字典中.
同样用字面量语法创建字典也有一个问题,那就是一旦有值为nil,程序便会抛出异常.这样也恰到好处提醒了程序猿们字典中有了空对象.同理"dictionaryWithObjectsAndKeys"则无法做到这一点.
还有一点就是通过键值来访问其值,通常的做法:
NSString *name = [dictionary objectForKey:@"firstName"];
与之等效的字面量语法是:
NSString *name = dictionary[@"firstName"];
可变数组和字典
对于可变的数组和字典,字面量语法不仅能访问到数组中某个下标对应的元素或字典中某个键对应的元素,还可以通过下标修改对应元素的值.
标准做法:
[mutableArray replaceObjectAtIndex:0 withObject:@"Ben"];
[mutableDictionary setObject:@"Ben" forKey:@"lastName"];
字面量语法:
mutableArray[0] = @"Ben";
mutableDictionary[@"lastName"] = @"Ben";
好处不言自明!
局限性
俗话说:金无足赤,人无完人.除了字符串以外,所创建出来的对象必须属于Foundation框架才行.如果自定义了这些类的子类,则无法使用字面量语法了.要想创建自定义子类的实例,必须采用"非字面量语法".不过也不建议这么做.因为NSArray, NSDictionary, NSNumber都是业已定型的"子族",很少有人会从其中自定义子类.真要这么做也比较麻烦.
使用字面量语法创建出来的字符串,数组,字典对象是不可变的.若想变成可变版本,需要复制一份.
NSMutableArray *mutableArray = [@[@1, @2, @3] mutableCopy];
这么做会多调用一个方法,而且还有再创建一个对象,不过笔者认为"功大于过"!
总结:
- 应该使用字面量语法来创建字符串, 数组, 数值, 字典.与创建此类对象的常规方法相比这么做更简洁明了.
- 应该通过取下标操作来访问数组下标或字典中键所对应的元素.
- 用字面量语法创建数组或字典时,若值为nil, 则会抛出异常, 因此, 务必确保值里不包含nil.