多用字面量语法,少用与之等价的方法

编写Objective-C程序是,总会用到某几个类,它们属于Foundation框架。虽然从技术上来说,不用Foundation框架也能写出Objective-C代码,但实际上却经常用到此框架。这几个类是NSSting,NSNumber,NSArray, NSDictionary。从类名上即可看出各自的数据结构。
Objective-C语法以繁杂而著称。事实上确是这样。不过,从Objective-C 1.0起,有一种非常简单的方式能创建NSSting对象。这就是“字符串字面量”(string literal),其语法如下:

NSSting *something = @"Effective Objective 2.0";

如果不用这种语法的话,就要以alloc及init的方法来分配初始化NSSting对象了。在版本较新的编译器中,也能用这种字面量语法来声明NSNumber,NSArray, NSDictionary类的实例。使用字面量语法(literal syntax)可以缩短源代码长度。使其更为已读

字面数值

有时需要把整数,浮点型,布尔值封入Objective-C对象中。这种情况下可以用NSNumber类,该类可处理多种类型的数值。若是不用字面量,那么就需按照下述方式创建实例:

NSNumber *someNumber = [NSNumber numberWithInt:1];

上面这行代码创建了一个数字,将其值设为1。然而使用字面量能令代码更为简洁:

NSNumber *someNumber = @1;

上述可以看到,字面量语法更为简洁。不过他还有更多好处。能够以NSNumber实例表示的所有数据类型都可以使用该语法。

NSNumber *intNumber = @1;
NSNumber *floatNumber = @1.1f;
NSNumber *doubleNumber = @3.14159;
NSNumber *boolNumber = @YES;
NSNumber *chatNumber = @'c';

字面量语法也适用于下述表达式:

int x = 5;
float y = 2.1f;
NSNumber *expressionNumber = @(x * y);

以上字面量表示数值十分有用。这样做可以令NSNumber变得整洁。因为声明中只包含数值,而没有多余的语法成分。

字面量数组

数组是常用的数据结构,如果不适用字面量语法,那么就这样来创建数组:

NSArray *animals = [NSArray arrayWithObjects:@"cat",@"dog",@"mouse",@"badger",nil];

如果使用字面量语法来创建则是:

NSArray *animals = @[@"cat",@"dog",@"mouse",@"badger"];

上面这种做法不仅简单,而且还利于操作数组。数组常见操作就是取某个下标所对应的对象,这用字面量来做更为容易。如果不用字面量,那么通常会用“objectAtIndex:”方法:

NSString *dog = [animals objectAtIndex:1];

若使用字面量方法则为:

NSString *dog = animals[1];

这也叫做“取下标”操作(subscripting),与使用字面量语法的其他情况一样,这种方式更为简洁,更易理解,而且与其他语言依据下标来去数组元素时所用的语法类似。
不过,用字面量语法创建数组是要注意,若数组对象中存在nil,则会抛出异常。因为字面量语法实际上只是一种“语法糖”(syntactic sugar),其效果等于是先创建了一个数组,然后把方括号内的所有对象都添加进这个数组中。抛出异常会这样:

*** Terminating app due to uncaught exception 
'NSInvalidArguementExcription', 
reason:'*** -[__NSPlaceholderArray initWithObjects:count:] : attempt to
inset nil object form objects[0]'

在改用字面量语法创建数组时就会遇到这个问题。下面这段代码分别用两种方式创建数组:

id object1 = /* ... */;
id object2 = /* ... */;
id object3 = /* ... */;

NSArray *arrayA = [NSArray arrayWithObjects:object1,object2,object3,nil];

NSArray *arrayB = @[object1, object2, object3];

如果Object1、Object3都指向了有效的Objective-C对象,而Object2指向了nil,会出现什么情况呢?按照字面量语法创建数组arrayB会抛出异常。arrayA虽然可以创建出来,但只包含一个Object1一个对象。原因是“arrayWithObjects:”会依次处理各个参数,知道发现nil为止,由于Object2为nil,所以方法会提前结束。
这个微妙的差别表明,使用字面量语法更为安全。抛出异常致应用程序终止执行,这比创建好数组之后才发现元素个数少了要好。向数组中插入nil通常会说明应用程序有错,而通过异常可以快速的发现这个错误。

字面量字典

字典(NSDictionary)是一种映射型数据结构,可向其中添加键值对。与数组一样,Objective-C也常用到字典,其创建方式如下:

NSDictionary *personData = [NSDictionary dictionaryWithObjectsAndKeys:
                                 @"Matt", @"firstName",
                                 @"Galloway", @"lastName",
                                 [NSNumber numberWithInt:28], @"age", nil];

这样写令人困惑,因为顺序是<对象>,<键>,<对象>,<键>。这通常与理解的顺序相反,我们一般认为是把“键”映射到“对象”上,因此,这种写法不容易懂。如果改为字面量语法,就清晰多了:

NSDictionary *personData = @{@"firstName" : @"Matt",
                             @"lastName" : @"Galloway",
                             @"age" : @28};

上面这种写法更加简明,而且键出现在对象之前,理解起来更顺畅。此示例代码还说明了使用字面量数值的好处。字典中的对象和键值都必须是Objective-C对象,所以不能把整数28直接放进去,而要将其封装在NSNumber实例中才行,使用字面量语法很容易就能做到这一点,只需给数字前加一个@符号即可。
与数组一样,用字面量常量创建字典时也有个问题,那就是一旦有值为nil,就会抛出异常。不过基于同样的原因,这也是个好事。假如在创建字典时不小心用了空对象,那么“dictionaryWithObjectsAndKeys:”方法就会在首个nil停下,并不会抛出异常,这有助于差错。
字典也可以向数组那样用字面量语法访问。按照特定键访其值的传统做法是:

NSString *lastName = [personData objectForKey: @"lastName"];

与之等效的字面量语法是:

NSString *lastName = personData[@"lastName"];

这样也省去了冗赘的语法,令此行代码更易读。

可变数组与字典

通过取下标操作,可以访问数组中某个下标或字典中中某个键对应的元素,如果数组与字典的对象是可变的(mutable),那么也能通过下标修改其元素。修改可变数组与字典内容的标准做法是:

[mutableArray replaceObjectAtIndex:1 withObject:@"dog"];
[mutableDictionary setObject:@"GalloWay" forKey:@"lastName"]

若换取下标操作来写,则是:

mutableArray[1] = @"dog";
mutableDictionary[@"lastName"] = @"GalloWay";

局限性

字面量语法有一个小小的局限,就是除了字符串以外,所创建出来的对象都必须属于Foundation框架才行。如果自定义了这些子类,则无法用字面量语法来创建其对象。要想创建自定义类的实例,必须采用非字面量语法(nonliteral syntax)。然而,由于NSArray,NSDictionary, NSNumber都是已经定型的子族,因此很少有人会从其中定义子类,真要那样做也比较麻烦。而且一般来说,标准的实现已经很好了,无需再改动。创建字符串时可以使用自定义子类,然而必须要修改编译器的选项才可以。除非你明白这样做的后果,否则不鼓励用此选项,用NSString就够了。
使用字面量语法创建出来的字符、数组、字典对象都是不可变的(immutable),若想要可变版本的对象,则需复制一份:

NSMutableArray *mutable = [@[@1, @2, @3 ,@4, @5]mutableCopy];

这样做会多调用一个方法,而且还有多创建一个对象,不过使用字面量语法多带来的好处是多余上述缺点的。

要点:

应该使用字面量语法来创建字符串、数值、数字、字典。与创建此类的常规方法相比,这么做更加简明扼要。
应该通过取下标的操作来访问数组或字典中的键所对应的元素。
用字面量语法来创建数组和字典时,若值中有nil,则会抛出异常,务必确保之中不包含nil。

此文章是读《Effective Objective-C 2.0 编写高质量iOS与OS X代码的52个有效方法》学习笔记:

第三条:多用字面量语法,少用与之等价的方法

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,108评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,699评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,812评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,236评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,583评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,739评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,957评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,704评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,447评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,643评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,133评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,486评论 3 256
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,151评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,889评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,782评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,681评论 2 272

推荐阅读更多精彩内容