只要你喜欢,你可以坐享keynote乐趣,兴奋的开始尝试所有最新的API。然后你可以竖起耳朵听新语言:Swift!它不是Objective-C的扩展,它是一门新的语言。你兴奋么?你开心么?也许你自己也不知道想什么。
Swift无疑将在未来改变我们编写的IOS和Mac应用的方式。在本文中,我简要概述一些Swift语言的亮点,并于Objective-C里对应的作对比。
类型@H_403_10@
第一重点是Swift提供的
类型推导。一种语言如果提供类型推导,那么程序员不需要注释变量的类型。编译器会自动根据变量去推断是什么类型并且设置这个变量。例如,编译器可以自动设置这个变量为String型:
- //automaticallyinferred
- varname1="Matt"
- //explicittyping(optionalinthiscase)
- varname2:String="Matt"
事实上这与Objective-C强壮动态的性质形成鲜明的对比。在Objective-C中,就是没有编译时候,其类型是知道的。在运行时,这是因为你可以在已存在的类中添加方法,添加全新的类和在实例中改变类型
让我们看更多地细节。参考下面的object-c:
- Person*matt=[[Personalloc]initWithName:@"MattGalloway"];
- [mattsayHello];
编译器调用sayHello时,它会去头文件检测声明的方法叫sayHello。如果没有就会报错,这就是它所要做的事情。它通常会在第一行跑出bugs信息给你。它可以捕捉如拼写错误,但是由于动态的特性,在运行时编辑器不知道sayHello的改变或者必要的存在。在协议中它是一个可选方法,例如(记住所有respindsToSelector: checks?)
由于缺乏强转类型,没有编译器可以在Objective-C调用方法时做优化。处理动态调度的方法叫obj_msgSend.我很确信的说你已经看到很多向后追踪!在这个方法中,选择器实现了向上然后跳。你不得不同意这增加开销和复杂性。
现在我们看下Swift里相似的代码:
- varmatt=Person(name:"MattGalloway")
- matt.sayHello()
在Swift中,在任何方法调用,编译器对相关类型了如指掌。它很快就定位sayHello()在哪里定义。正是基于此,它跳过动态调度而立即跳向实现达到充分利用优化的效果。此外,在Objective-C它使用vtable风格调度,开销远低于动态调度。这种调度在c++中使用虚函数。
泛型@H_403_10@
一个经常用的到结构体例子。你想同时存值,在Swift里你需要像下面实现的方式做:
- structIntPair{
- leta:Int!
- letb:Int!
- init(a:Int,b:Int){
- self.a=a
- self.b=b
- }
- funcequal()->Bool{
- returna==b
- }
- }
- letintPair=IntPair(a:5,b:10)
- intPair.a//5
- intPair.b//10
- intPair.equal()//false
这非常有用!你可能不是很清楚为什么是这样的特性,但请相信我:机会永远是无穷无尽的。很快你就会在你的代码中随意应用。
容器@H_403_10@
你熟悉并喜爱着 NSArray,NSDictionary 以及它们的可变副本。好了,现在你要学习Swift中等价的容器了。幸运的是,它们非常相似。下面是如何声明一个数组和字典:
- letarray=[1,2,3,4]
- letdictionary=["dog":1,"elephant":2]
你应该对他们很熟悉。但有一个细微差别。在 Objective-C 中,数组和字典可以包含任何你希望的类型。但是在 Swift 中,数组和字典有类型限制,并且通过上面提到的“泛型”的使用来限定类型。
两个以上的变量可以用它们的表达类型来重写(但记住你并不需要真的这么做),如下:
- letarray:Array<Int>=[1,4]
- letdictionary:Dictionary<String,Int>=["dog":1,serif"> 注意:@H_403_10@泛型是如何用来定义容器的存储的。还有一个数组的缩写形式,这个更具有可读性,但本质上是一样的。