Xcode 4.4发行说明中提到的“Objective-C Literals”的细节是什么?

What are the details of “Objective-C Literals” mentioned in the Xcode 4.4 release notes?

我浏览了xcode 4.4的发行说明,注意到了这一点:

LLVM 4.0 Compiler

Xcode now includes the Apple LLVM Compiler version 4.0, including the following newObjective-C language features:
[...]
- Objective-C literals: create literals for NSArray, NSDictionary, and NSNumber, just the same as the literals for NSString

我对这个功能很感兴趣。我不太清楚NSString的文字是如何工作的,以及人们如何在NSArrayNSDictionaryNSNumber上使用它们。

细节是什么?


从http://cocaheads.tumblr.com/post/17757846453/objective-c-literals-for-nsdictionary-nsarray-and:

Objective-C文本:现在可以为nsarray、nsdictionary和nsnumber创建文本(就像可以为nsstring创建文本一样)

非数组文字

先前:

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

现在:

1
array = @[ a, b, c ];

nsDictionary文本

先前:

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

现在:

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

nsnumber文本

先前:

1
2
3
4
5
6
7
8
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];

现在:

1
2
3
4
5
6
7
8
NSNumber *number;
number = @'X';
number = @12345;
number = @12345ul;
number = @12345ll;
number = @123.45f;
number = @123.45;
number = @YES;

[编辑]

ZXOQ在http://news.ycombinator.com/item?ID=3672744添加了更有趣的新订阅。(添加文字):

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

[编辑2 ]

新的objc文本在多个WWDC 2012会议上进行了讨论。我故意不删除每张幻灯片的文件名和时间,这样你可以自己找到它们。它们本质上与本文所述的相同,但在图片上方我也会提到一些新的东西。

请注意,图片都很大。只需将它们拖动到另一个选项卡中,即可按原始大小查看它们。

Literals & Boxing

1
2
3
4
[NSNumber numberWithint:42]
[NSNumber numberWithDouble:10.8]
[NSNumber numberWithBool:YES]
[NSNumber numberWithint:6 + x * 2012]

Literals & Boxing

1
2
3
4
@42
@10.8
@YES
@(6 + x * 2012)

Collection Subscripting

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

Collection Subscripting

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

@# numbers, @{} dictionaries, @

这部分是新的。表达式文本

当您有一个表达式(例如M_PI / 16)时,您应该将它放在括号内。

此语法适用于数字表达式、布尔值、在(c-)字符串中查找索引、布尔值、枚举常量甚至字符串!

Expression Literals

1
2
3
4
5
6
7
8
9
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")];

Expression Literals

1
2
3
4
5
6
7
8
9
NSNumber *piOverSixteen = @( M_PI / 16 );

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

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

NSNumber *writingDirection = @( NSWritingDirectionLeftToRight );

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

有关字符串以及如何/何时可以使用此文本语法的详细信息:

Boxed String Expressions

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

Boxed String Expressions

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

数组文字如何工作

How array literals work

1
2
3
4
5
6
7
// 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];

字典文本如何工作

How dictionary literals work

1
2
3
4
5
6
7
8
9
10
// 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];

关于数组订阅的更多信息

Array Subscripting

1
2
3
4
5
6
7
8
9
@implementation SongList {
    NSMutableArray *_songs;
}

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

Array Subscripting

1
2
3
4
5
6
7
8
9
@implementation SongList {
    NSMutableArray *_songs;
}

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

有关词典订阅的更多信息

Dictionary Subscripting

1
2
3
4
5
6
7
8
9
@implementation Database {
    NSMutableDictionary *_storage;
}

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

Dictionary Subscripting

1
2
3
4
5
6
7
8
9
@implementation Database {
    NSMutableDictionary *_storage;
}

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

[编辑3 ]

Mike Ash对这些新的文字有很好的描述。如果你想更多地了解这些东西,一定要去看看。


Objective-C编译器对NSConstantString类(也称为__CFConstantString类)实例的内存布局有硬编码的知识。查看clang源代码中lib/Rewrite/RewriteModernObjC.cpp中的RewriteObjCStringLiteral函数。编译器只发出与NSConstantString类的实例布局相匹配的数据。

对于文字上的NSArrayNSDictionary实例,有两种可能。它们可以像处理文字字符串那样做——在编译器中对实例布局(对于特殊子类)进行硬编码,并在该布局中发出数据。或者他们可以让编译器发出代码,在运行时简单地创建一个实例。


来自"Objective-C Literals"

1)xcode 4.4中提供了NSNumberNSDictionaryNSArray文本。

2)NSDictionaryNSArray订阅需要"xcode 4.4和os x 10.8或更高版本的sdk"或"xcode 4.5和ios 6或更高版本的sdk"

在我看来,订阅需要运行时支持,因此在ios6之前无法工作。