Objective-C中是否存在字面量的字典或数组语法?

54

一直以来,我们都可以使用变长参数的方式创建NSArray(以及NSDictionaries/NSNumber),例如:

[NSArray arrayWithObjects: @"a", @"b", @"c", nil];

这些能否通过LLVM和Clang的新改进使用内联字面量创建?

2个回答

120

随着LLVM代码库中这个更改,Apple在即将推出的Clang编译器的新版本中添加了一种新的字面量语法。

之前,数组是使用基于C的数组创建的,并在转换为Objective-C对象时进行动态转换,例如:

NSArray* array = [NSArray arrayWithObjects: @"One", @"Two", @"Three", nil];

请注意,由于这是一个 varargs 元素,您必须在列表末尾提供一个结束的 'nil'。但现在有一种更简单的方法:

NSArray* array = @[ @"One", @"Two", @"Three" ];

需要注意的是,[] 前面的 @ 是必需的,以区分它和普通的 C 数组(或消息发送)。还要注意,不再需要使用 'nil' 作为结尾。

类似的更改也已经针对内联字典字面量进行了,就像 JSON 结构一样:

NSDictionary* dict = @{
    @"Key1": @"Value1",
    @"Key2": @"Value2",
};

最后,已经添加了一个新的NSInteger(等)字面值:

NSNumber* value = @3.141;
请注意,尽管这适用于浮点数(@3.141F)和双精度浮点数(@3.141),但不适用于long double,因为编译器不支持对其进行包装。 因此,@3.141D将导致编译时错误。
由于常量的定义方式,@INT_MAX是一个有效值,但@INT_MIN不是,因为后者是通过编译时表达式而不是字面量本身定义的。
还有布尔类型的扩展:
NSNumber* yes = @YES;         // [NSNumber numberWithBool:YES]
NSNumber* no = @NO;           // [NSNumber numberWithBool:NO]
NSNumber* trueBool = @true;   // [NSNumber numberWithBool:(BOOL)true]
NSNumber* falseBool = @false; // [NSNumber numberWithBool:(BOOL)false]

这个变化还引入了__objc_yes__objc_no字面量,仅通过文字值支持类型解析。它们的使用受到预处理器中#if __has_feature(objc_bool)的保护,但开发人员应继续在代码中使用YESNO

最后,数组和字典现在都可以使用数组括号进行下标访问,可用作lvaluervalue表达式:

NSMutableArray* stuff = ...
id first = stuff[0];
stuff[0] = anotherObject;

NSMutableDictionary* moreStuff = ...
id conference = moreStuff[@"NSConf"]
moreStuff[@"SponsoredBy"] = @"NSConfDuck"

使用数组样式的下标(使用NSUInteger)将映射到objectAtIndexedSubscript:和相应的setObject:atIndexedSubscript:,而字典访问则使用objectForKeyedSubscript:setObject:forKeyedSubscript:

完整的语法可以在Clang/LLVM网站上查看。

请注意,自从此答案最初编写以来,Clang已经添加了对名为“Boxed expressions”的非字面意义的Objective-C表达式的支持。

这意味着可以使用@(3+4)等效于@7@("Hello World")等效于@"Hello World"。请注意,求值为null的C表达式将导致异常,并且诸如@(null)之类的参数被视为编译时错误。

还可以使用“Boxed enums”来处理已知类型的类型,例如:

enum { North, South, East, West, };

可以使用@(North)将其放入一个boxed枚举类型中,它的值将为0

Clang 3.2及更高版本将提供Boxed expressions。它可以使用__has_feature(objc_boxed_expressions)预处理器测试进行测试。


现在还有自动装箱表达式,在此答案首次发布后创建。我已经修改了上面的列表,以包括一些示例。 - AlBlue
2
我必须说,对于NSNull来说,一个@nil会很好。 - Joe
我认为 "id first = stuff[@0];" 是错误的。我认为它必须是 "id first = stuff[0];" 以避免编译时错误。 - Steve McLeod
我认为NSDictionary的创建使用@{}很奇怪,而对于访问它使用dict [key]。我不太喜欢括号类型的切换。为了保持一致性,我更希望他们使用 dict{key} 作为访问方式。 - poetmountain

6
NSNumber *intNumber1 = @42;
NSArray *array1 = @[@"foo", @42, @"bar", @3.14];
NSDictionary *dictionary1 = @{ @1: @"red", @2: @"green", @3: @"blue" };

来源:http://blog.ablepear.com/2012/02/something-wonderful-new-objective-c.html

本文介绍了Objective-C 2.0的一些新特性,包括属性语法、快速枚举和块。通过属性语法,我们可以更方便地声明实例变量。快速枚举则可在遍历集合时使代码更加简洁。块则是Cocoa中广泛使用的一种闭包技术,可以在方法间传递代码块。这些新特性都能够提高开发效率,让Objective-C编程更加轻松愉快。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接