第1章 未来的iOS开发语言Swift语言介绍
苹果(Apple)公司最近动作还是比较多的,除了即将推出的iWatch 等新硬件产品外,还推出了一种新的编程语言Swift。可能初次接触苹果软件开发的程序员对Swift还很陌生,当然,这也不奇怪,因为在写这本书时,Swift才刚刚推出。不过,由于Swift出身贵族,这也注定了Swift将拥有一个美好的未来,很可能成为苹果软件开发体系的中坚力量。既然Swift如此重要,作为求知欲极强的程序员们怎能放过这么一个成为国内,不!应该说世界上首批Swift专家的机会呢!现在就让我们开启Swift语言的开发之旅吧!
本章要点
□ Swift语言简介
□ Swift开发环境搭建
□ 创建Swift工程
□ 编写一段简单的Swift语言代码
□ 所见即所得的Playground
1.1 Swift语言的前世今生
在2014年的苹果WWDC大会上,最大的亮点当属Swift的出现了。因为苹果一贯以硬件为主,这次突然弄出了软件,而且还是生产软件的软件:Swift语言。自然会引起各方的广泛关注。国内外在 24 小时内推出了大量关于Swift语言的学习资料,甚至视频 。我就从来没看过一种新技术被如此关注过,因为当年我赶上了微软C#的首发、还有Google的Go语言首发,关注度都没有Swift语言高,看来业界对这个一直玩硬件的苹果突然推出一种新编程语言还是很看好的。这么说当然是有证据的,就在Swift语言刚推出不到一个月的时间里,已经排到了编程语言的第16位,这在以前从未发生过。
既然说到Swift语言,那么就必须要提一下Swift的发明者Chris Lattner(可以叫他克里斯),Chris博士毕业,是一个全面发展的好学生。
据说Chris最喜欢看的IT著作是龙书,还喜欢在旅游时带这本书。别人旅游时都看小说或看Video,这家伙却看编译原理的书,的确高大上。高手就是与别人不一样(就在写这本书时,我已经将龙、虎、鲸3本书的英文电子版放到平板电脑里了,准备旅游时看)。
下面主要来谈谈Chris的光荣事迹。Chris在硕士毕业时提出了一套完整的运行时编译思想,奠定了LLVM 的发展基础。在博士期间继续领导LLVM编译框架向前发展,并取得了长足的进步。LLVM已经可以基于 GCC 前端编译器的语义分析结果进行编译优化和代码生成,所以,Chris在2005年毕业时已经是业界知名的编译器专家了。
苹果在2005年雇佣了Chris。Chris在苹果的几年中不仅大幅度优化和改进LLVM以适应Objective-C的语法变革和性能要求,同时发起了CLang项目,旨在全面替换GCC,现在这个目标已经实现了。从OS X 10.9和XCode 5开始,LLVM+GCC已经被替换成了LLVM+CLang。
在2010年,Chris接到了一个不同寻常的任务,就是为iOS和OS X平台开发下一代的编程语言,这就是现在看到的Swift。最初Swift完全是由Chris开发的。只是在一年后(2011年),才陆续有若干编译器专家加入了Swift团队。终于在4年后的2014年,Swift的第一个版本在苹果的2014年WWDC大会上向我们展示了她的魅力。
1.2 Swift到底是怎样的一种语言
Swift是一门博采众长的现代语言,在设计的过程中,Chris参考了Objective-C、Rust、Haskell、Ruby、Python、C#等优秀语言的特点,最终形成了目前Swift的语法特性。这也是为什么使用各种语言的程序员都能从Swift中找到自己熟悉的影子的原因。那么,Swift语言到底是一种怎样的语言。可以从下面几方面初步了解一下Swift语言。
(1)Swift是面向对象的、编译型语言。编译时底层需要通过LLVM 生成本地代码才能执行,所以效率还是很高的。
(2)Swift可以使用Cocoa和Cocoa Touch中的API。这也就意味着Swift与Objective-C一样,拥有了一个强大的Framework Library。
(3)Swift吸取了很多编程语言的优点,同时Swift又具备了很多动态语言的语法特性和交互方式,当然,Swift本身是静态语言。所以,Swift尽可能地在静态语言和动态语言之间寻找平衡点。
(4)既然说Swift是一种拥有动态特性的静态语言,那么Swift自然就是一门类型安全的语言。编译器可以在编译过程中检测出类型异常。例如,如果你期望为一个字符串变量赋值,那么类型安全机制会阻止你为这个变量设置整数。正是由于类型安全机制的存在,使开发者可以更早地发现并修复错误。
(5)支持各种高级语言特性,包括闭包、泛型、面向对象、多返回值、类型接口、元组、集合等。
(6)Swift能与Objective-C进行混合编程,但代码分属不同的文件。
(7)全面支持Unicode编码。也就是说,可以用任何想用的字符作为变量名,例如,一个笑脸字符或汉字。图1-1就是使用笑脸图标和汉字作为变量名的一个典型例子。
▲图1-1 使用笑脸图标和汉字作为变量名
(8)使分号(;)变成了可选的符号。通常的静态语言,如Java、C#。每条语句结束后,都会在最后加上“;”,而Swift的每条语句不需要加“;”,当然,加上也没问题。只有在两条或多条语句写在同一行时才必须加“;”。
(9)简化和增强了集合数据类型。用过Java和C#的读者知道。在这两种语言中,各种集合类型不可谓不全,但太多也有它不好的地方,就是不知道使用哪个。而且这些集合数据类型的功能也不够强大。在Swift语言中只提供了数组(Array)和字典(Dictionary)两个集合数据类型。其中Array类似List的功能,可以修改、添加、替换和删除数组元素。Dictionary类似Map的功能,用于存储Key-Value 风格的值。
(10)Swift可以通过元组实现函数返回多个值。这一功能在其他语言中需要通过返回一个对象或结构体(指针)来实现。
(11)提供了优雅的闭包解决方案。例如,在排序函数 sort 中可以将函数作为参数值传递。下面的代码是一种典型的写法:
let array1 = ["X", "A", "1", "2", "Z"]
func backwards(s1: String, s2: String) -> Bool
{
return s1 > s2
}
var array2 = sort(array1, backwards)
当然,更简洁的写法是var array2 = sort(["X", "A", "1", "2", "Z"] ) { $0 > $1 },如果读者不明白这么写是什么意思,那么就继续往后看吧!
(12)Swift语言中提供了一种可选变量(Optional)。主要是为了应对一个变量可能存在,也可以是 nil 的情况。例如,将一个字符串(String)转换为整数(Int),但这个字符串是否可以成功转换为整数呢?如果不确定,就返回一个可选变量。如果成功转换,则返回正常的整数值;如果转换失败,则返回nil。实现的代码如下:
let str = "126CB5"
let value = str.toInt() // value是一个可选常量(用let声明是常量,用var声明是变量)
这时,value就是一个可选变量。要想判断转换是否成功,可以使用下面的代码:
if value
{
// 如果value是可选变量,引用时需要加上“!”,
// 表示该选项变量中肯定有一个值
println(value!)
}
可选变量的引入解决了大部分需要显式处理的异常,这部分工作也扔给编译器去做了。
(13)拥有不同意义的nil。在Swift中的nil和Objective-C中的nil不同。在Objective-C中,nil是指向不存在对象的指针,而在Swift里,nil不是指针,它表示特定类型的值不存在。所有类型的可选值都可以被设置为nil,不仅是对象类型。
(14)Swift中没有从语言层面支持异步和多核,不过可以直接在Swift中复用GCD(Grand Central Dispatch)的API实现异步功能。
(15)Swift没有一部处理机制。可能是认为有了可选变量,异常会很少使用,所以未加入异常处理。
1.3 Swift开发环境搭建
尽管Swift语言拥有独立的编译器,不过,目前Apple并没有单独发布Swift开发包。所以只能连同XCode 6一起安装来使用Swift语言。由于XCode 6仍然是Beta版,所以,Apple并未对所有的人开放下载XCode 6,只有拥有苹果开发者账号 的用户才允许下载XCode 6 Beta版。如果读者不舍得那99美金也不要紧,我已经将XCode 6 Beta的安装文件上传到的网盘,下载地址是http://pan.baidu.com/s/1hq7mAOk,下载后是一个dmg文件(2.33G左右),直接在Mac OS X下双击安装即可。XCode 6是可以和Xcode 5或其他版本共存的,所以不必担心,尽管安装。
安装完后,在 Mac的“应用程序”列表中多了一个“Xcode6-Beta.app”,直接双击运行即可。成功运行后,点击XCode6中的“Xcode”>“About Xcode”菜单项,如果能看到如图1-2 所示的窗口,并且 Version 显示的是 6.0,则说明 XCode6 已经安装成功了。
▲图1-2 XCode 6的About 窗口
1.4 创建Swift工程(OS X和iOS平台)
Swift 语言可以开发 iOS 和 OS X 两个平台的程序,读者可以选择自己喜欢的平台学习Swift语言。如果有苹果开发者账号的,最好选择iOS平台,因为可以在iPhone上测试全部的功能。如果没有开发者账号,可以考虑选择OS X 平台,否则就只能在iOS模拟器上测试Swift 程序了。不管是创建哪个类型的工程,首先需要点击“File”>“New”>“Project”菜单项打开如图1-3所示的工程模板选择窗口。
▲图1-3 创建 iOS 工程
如果选择iOS平台,通常选择“Application”,然后在右侧工程模板列表中选择一个,如“Single View Application”,如 图1-3所示。
如果读者选择 OS X 平台,可以选择“Application”,并在右侧的工程模板列表中选择“Command Line Tool”(一个终端工程模板),如图1-4所示。
▲图1-4 创建Mac工程
接下来可以点击“Next”按钮进入下一步的设置。在下一步中需要输入工程名和工程支持的语言(为了测试方便,这里选择了OS X 平台,等涉及iOS 部分时,再创建iOS 工程)。当然,我们需要选择“Swift”,如图1-5所示,然后点击“Next”按钮进入下一步。在下一步中需要选择一个用于存放工程的目录,选择完成后,点击“Create”按钮,就会创建一个OS X工程。
▲图1-5 建立 iOS工程,选择 Swift 语言
图1-5是OS X 工程的机构,其中新创建了一个main.swift文件。该文件用于输入Swift语言的代码。
在main.swift文件中默认生成了如下的代码:
import Foundation
println("Hello, World!")
直接运行该工程,就会在输出视图中输出“Hello, World!”。
如果读者要建立 iOS for Swift 工程,这里假设选择了图1-3 所示的“Single View Application”模板,在下一个设置页面输入工程名(如 first_swift_ios)后再进入下一个设置页面,选择存储目录后可创建iOS工程,工程结构如图1-7所示。
▲图1-6 OS X 工程结构
▲图1-7 iOS 工程结构
如果运行这个工程,首先会启动iOS模拟器(要选择iOS8模拟器),然后在模拟器中会运行一个 iOS 程序,该程序并没有任何 UI,背景为白色。本书后面的章节会介绍如何使用Swift开发iOS应用和游戏。
对于只想学习一下Swift语言的读者,建议还是使用OS X终端程序为好,因为OS X终端程序运行快速简单,可以排除其他的干扰。
1.5 瞧一瞧Swift到底长啥样
可能很多读者看到前面的介绍后跃跃欲试,想试一试 Swift 语言,不过先别忙,在正式编写Swift语言之前,先了解一下Swift语言的语法和样式是非常必要的。就像搞对象,起码得先看看对方长啥样,然后才能进行下一步。现在就让我们看看Swift到底长啥样。
Swift 语言和其他语言(如 Java、C#、Objective-C)类似,也支持一些常规的操作和语法元素,例如,运算符(+、−、*、/、%、++、&&、||等)、数据类型(字符串、数值等)、控制语句(if、switch、for)、类、方法(函数)等。不过 Swift 添加了很多特有的语法元素(至少是大多数语言都不具备的技术),例如,类扩展、增强的switch语句、小标、元组类型、返回多种的方法(函数)等。下面是一段标准的Swift语言代码,尽管没有枚举Swift中所有的新特性,但足够让我们充分了解 Swift 语言的基本语法规则。如果读者对某些表达式不理解也没关系,在后面的章节会深入介绍这些特有的语法规则。
import Foundation
var value1 = 20 // 定义并初始化一个整型变量
value1 += 35
// 输出:value1=55
println("value1=\(value1)")
let value2 = 42 // 定义并初始化一个整型常量
// 输出:97
println(value1 + value2)
// 定义并初始化一个数组变量
var array1 = ["abc","bbb","ccc"]
// 枚举数组中的每一个元素值
// 输出:abc bbb ccc
for element in array1
{
print(element + " ")
}
// 定义函数,返回值类型是String
func getPerson(name: String, age:Int) -> (String)
{
return "name:" + name + " age:" + toString(age)
}
println()
// 调用getPerson函数
let person = getPerson("bill", 50)
// 输出:person:name:bill age:50
println("person:\(person)")
// 定义一个可以返回多个值的函数(返回两个值:name和price)
func getProduct() -> (name:String, price:Float)
{
return ("iPhone6", 6666.66)
}
// 输出:(iPhone6, 6666.66015625)
// 调用getProduct函数,并输出其返回值
println(getProduct())
// 输出:product name: iPhone6
// 输出getProduct函数返回name值
println("product name: \(getProduct().name)")
// 定义Country类
class Country
{
var name = "China"
let area: Float = 960
// 定义一个成员方法
func getDescription() -> String {
return "Country:\(name) Area:\(area)"
}
}
// 创建一个Country类型的常量
let country = Country()
// 输出:Country:China Area:960.0
// 调用Country.getDescritpion方法,并输出该方法的返回值
println(country.getDescription())
// 定义一个类扩展,相当于将一个类的某一部分拿出来单独定义
extension Country
{
// 为Country类添加一个方法
func getAddress() -> (planet: String, location:String)
{
return ("Earth","Asia")
}
}
// 输出:Planet:Earth
// 调用扩展方法getAddress,并输出返回值中的planet
println("Planet:\(country.getAddress().planet)")
// 输出:Location:Asia
// 调用扩展方法getAddress,并输出返回值中的location
println("Location:\(country.getAddress().location)")
如果执行上面这段代码,会输出如下的信息。
value1=55
97
abc bbb ccc
person:name:bill age:50
(iPhone6,6666.66015625)
productname: iPhone6
Country:China Area:960.0
Planet:Earth
Location:Asia
1.6 所见即所得的Playground
XCode 6新增加了一个Playground,在iOS和OS X工程中都可以使用Playground。这个东西其实就是一个所见即所得的写代码的文件。这里的所见即所得就是编写代码后,不需要运行,立刻会显示出结果,并且还可以显示出代码中某个变量/常量的当前值。Playground比较适合于测试Swift语言的代码。但Playground在输出结果时可能会有些慢,而且写代码时会有些迟钝。这可能是因为需要实时解释Swift代码的原因!
要想使用 Playground,需要先创建 Swift 工程(iOS 和 OS X 工程都可以),然后在当前工程中点击“File”>“New”>“File”菜单项,会弹出一个如图1-8所示的窗口。在“iOS”和“OS X”中都有一个“source”节点,在该节点中都有一个“Playground”模板。不管是什么工程,选择哪个“source”节点下的“Playground”都可以。
▲图1-8 选择“Playground”模板
选择“Playground”模板后,进入下一个设置页面。在该设置页面中需要选择playground文件的存储目录,通常和 Swift 文件放在同一个目录中。如果下方的“Targets”列表中的工程未选择,需要选择该工程,效果如图1-9所示。
▲图1-9 创建 Playground 文件
如果成功创建了Playground文件,在工程目录中会多了一个文件扩展名为“playground”的文件。默认是 MyPlayground.playground。如果读者将上一节的代码都复制到MyPlayground.playground文件中,就会在代码右侧输出相应的结果,并且在输出结果和代码之间的部分还会显示当前变量/常量的当前值,效果如图1-10所示。
▲图1-10 Playground 的效果
1.7 小结
相信看完本章后,读者已经对 Swift 语言有了一个大致的了解。也学会了如何搭建实验环境。不过真正的Swift开发之旅才刚刚开始。后面还有Swift的语法、内置函数、iOS应用程序开发、基于SpriteKit游戏引擎的游戏程序开发等知识要学习。下面就让我们整装待发,去欣赏Swift给我们的一次又一次震撼吧!