LLVM 4新功能

自从Xcode 4.2同ios5一起发布,默认的编译器就是LLVM3.0了。 苹果从GCC切换到LLVM的一个目的是对Objective-C语言拥有更大的控制权。例如在Xcode 4.4中,苹果通过添加对字面量的支持使得Objective-C更加简洁。正是LLVM给了苹果这种改变Objective-C语言的能力。

 字面量

  字面量并不是什么新东西,Objective-C中一直以来都有字面量。接下来看一个简单的NSString声明语法。
1、NSString

NSString *greeting = [[NSString alloc] initWithCString:"Hello World!" encoding:NSUTF8StringEncoding]; //第一种方法:不使用字面量

//第二种方法:使用字面量
NSString  *greeting = @"Hello World !";

2、由标量直接创建NSNumber

NSNumber 是Foundation库中的一个类对象,而数值1、2、3是标量。

 NSNumber *number = [NSNumbernumberWithInt:1];

 NSNumber *yesValue = [NSNumbernumberWithBool:YES];


有了LLVM 4,你可以使用如下语法来简化代码:

 NSNumber *number =@1;

 NSNumber *yesValue =@YES;

也可以通过添加F后缀来告诉编译器将标量转为float类型。通过添加后缀U来将标量转换为无符号整型。

 NSNumber *valuePI =@3.14F;//使用float字面量声明一个NSNumber对象

 NSNumber *radius =@3U;//使用无符号integer字面量声明一个NSNumber对象


3、集合字面量(NSArray 和 NSDictionary)

    NSString *str1 =@"Hello";

   NSString *str2 = @"World";

   NSString *str3 = @"!";

   NSArray *myArray1 = [NSArrayarrayWithObjects:str1,str2,str3,nil];//用旧方法创建一个数组。


   NSArray *myArray1 = @[str1,str2,str3];//用集合字面量创建一个新数组。

使用字面量,不必再用nil标示数组末尾,编译器自动完成这一任务。


把前面学过的集合字面量和数字标量结合起来可以很方便地创建一个NSNumber数组,如下所示:

 NSArray  *arrayOfIntegers =@[@1,@2,@3,@4];


使用字面量创建NSDictionary

NSDictionary *dictionary =@{@"key1" :@"value1",

                             @"key2" :@"value2"};

字典的key和value也不再是倒着先写value,再写key了;

在 LLVM 4以前,虽然标量数组支持下标操作,但是NSArray 和 NSDictionary并不支持通过下标访问元素。需要使用 objectAtIndex:方法来访问NSArray中的元素,使用

valueForKey:方法访问NSDictionary中与某个键对应的值。在 LLVM4中,苹果为对象引入了下标访问操作符。

    

  NSArray *array =@[@1,@2,@3,@4,@5];

  int elementAt3 = array[3];

通过下标访问字典元素


 NSDictionary *dict =@{@"key1" :@"value1" ,

                          @"key2" : @"value2" ,

                          @"key3" : @"value3" ,};

 id elementAt3 = dict[@"key3"];


更多的示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  // 整数
  NSNumber *fortyTwo = @42;             // 等价于 [NSNumber numberWithInt:42]
  NSNumber *fortyTwoUnsigned = @42U;    // 等价于 [NSNumber numberWithUnsignedInt:42U]
  NSNumber *fortyTwoLong = @42L;        // 等价于 [NSNumber numberWithLong:42L]
  NSNumber *fortyTwoLongLong = @42LL;   // 等价于 [NSNumber numberWithLongLong:42LL]

  // 浮点数
  NSNumber *piFloat = @3.141592654F;    // 等价于 [NSNumber numberWithFloat:3.141592654F]
  NSNumber *piDouble = @3.1415926535;   // 等价于 [NSNumber numberWithDouble:3.1415926535]

  // 布尔值
  NSNumber *yesNumber = @YES;           // 等价于 [NSNumber numberWithBool:YES]
  NSNumber *noNumber = @NO;             // 等价于 [NSNumber numberWithBool:NO]

  // 空数组
  NSArray * array = @[];                // 等价于 [NSArray array]
  // 空的字典
  NSDictionary * dict = @{};            // 等价于 [NSDictionary dictionary]

怎么样?是不是简单多了?而且,为了方便你的旧代码迁移到新的写法,xcode专门还提供了转换工具,在xcode4.4中,选择 Edit -> Refactor -> Convert to Modern Objective-C Syntax即可。

局部的函数调用不用前向申明

这虽然是一个挺小的改进,但是很贴心。假如我们在一个源文件中有2个函数:分别名为foo 和 bar,其中foo的定义在bar前面。那如果在foo函数内部直接调用bar,编译器会报警告说找不到函数bar。

而现在,我们可以随意地在源文件中放置函数bar的位置。编译器在找不到bar时,会再源码后面找,如果找到了bar,就不会报错了。

带有类型的enum

现在我们可以定义enum是无符号整数还是整数,这样编译器会更加智能的做类型检查。如下所示:

1
2
3
4
5
6
7
8
9
10
typedef enum TableViewCellType : NSInteger {
    TableViewCellTypeQueue,
    TableViewCellTypeNewFans,
    TableViewCellTypeUserInfo,
    TableViewCellTypeOrganization,
    TableViewCellTypeFeedback,
    TableViewCellTypeRateApp,
    TableViewCellTypeRecommendation,
    TableViewCellTypeLogout
}TableViewCellType;

默认生成@synthesize代码

以前写完一个诸如 @property (nonatomic, strong) NSString * username; 变量定义后,马上得转到 .m文件中去增加相应的 @synthesize username = _username; 代码。

现在,编辑器发现你没有写 @synthesize时,会自动帮你加上这一行。这同时在另一方面,起到了鼓励大家使用以下划线开头的变量名作为成员变量名的作用。

当然,为了向下兼容,如果你的程序里面已经有了 @property 变量对应的 @synthesize 代码时,编辑器就不会自动帮你增加这个代码了。

另外有2种特殊情况下,即使你没有写 @synthesize ,编辑器也不会自动帮你加上,这2种情况是:

  1. 你同时提供了该property的setter 和 getter方法。
  2. 你的这个property是 readonly 的。

遍历元素

你是如何遍历数组的元素的?通常我们有2种做法,一种是用 for in,另一种是用一个变量来循环数组下标。如下:

1
2
3
4
5
6
7
8
    NSArray * lines = ...
    for (NSString * line in lines) {
       // ...
    }
    for (int i = 0; i < lines.count; ++i) {
        NSString * s = [lines objectAtIndex:i];
        ...
    }

如果是字典,遍历的代码就要稍微复杂一点了:

1
2
3
4
5
6
    NSDictionary * dict = 
    NSArray * keys = [dict allKeys];
    for (NSString * key in keys) {
        NSString * value = [dict objectForKey:key];

    }

现在,xcode对于iOS4.0以上的系统,支持用block来遍历元素了。用block来遍历字典可以简化代码的编写,建议大家都使用上这个新特性。

1
2
3
4
5
6
7
[lines enumerateObjectsUsingBlock:^(NSString * obj, NSUInteger idx, BOOL *stop) {

}];

[_urlArguments enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {

}];

Subscripting Methods

这个新特性在WWDC2012的视频中提到了,但是在XCode4.4中没有实现。也是一个很体贴的语法糖,它允许你用中括号来代替原本的方法来获取和设置数组元素。

简单来说,以前的 [array objectAtIndex:idx] 和 [array replaceObjectAtIndex:idx withObject:obj],可以直接写作 array[idx] 和 array[idx] = obj了。其实这个特性在很多高级语言中都实现了,只是Objective-C生于80年代,一直没改进这个。

这个改进同样对NSDictionary有效。甚至,你也可以给你自己的类提供中括号操作符对应的方法。具体做法是实现如下两个方法:

1
2
- (id)objectAtIndexedSubscript:(NSUInterger)idx;
- (void)setObject:(id)value atIndexedSubscript:(NSUInteger)idx;

期等XCode4.5中能够使用上这个特性。

Tips

上面提到了不用写 @synthesize 了,那原本写的那么多 @synthesize 怎么办呢?作为有代码洁癖的我很想把它们删掉,但怎么删呢?一个文件一个文件打开,然后行一行删掉吗?放心,苹果已经帮我们想了解决方案。在WWDC2012 Session 400 Developer Tools Kickoff 中,苹果介绍了具体做法。步骤如下:

  1. 首先使用区域查找,因为一般项目都会依赖第三方的开源库,我们可不想更改别人的库,所以我们只查找我们库中的文件,如下图所示:

  1. 接着我们用正则匹配,找到以 @synthesize开头,后面接着是 var = _var; 格式的行。插入正则表达式很简单,直接点击查找输入框左边的放大镜,选择“insert pattern”,苹果就会把常见的正则表达式都列出来,你直接选择就可以了,非常方便。如下图所示:

在插入好合适的正则表达式后,我们按回车,就可以搜索到结果。

  1. 我们点击搜索界面的preview按钮,查看替换效果,可以看到,对于我们测试代码,XCode生成的预览图已经正确地当对应代码删掉了。然后我们就可以点击替换,去掉所有的 @synthesize 代码了。

在下载完XCode4.4后,我就把我们的工程代码都转换成了新特性的语法。在转换后,我发现原本25000行的代码少了将近1000行。心里还是很开心的,因为又可以少写一些体力活类型的代码了。

还是那句话,希望这些新特性能够让大家玩得开心。

参考资料



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值