在上一篇中我们已经大致讲解过了Playground的作用了,现在我们就开始利用这个工具来学习Swift的语法。
首先,我们要说的是如何创建一个新的Playground,其实步骤很简单:
打开Xcode6,一次点击File->New->Playground…,即弹出如下图所示界面:
输入Playground的名称,并点击Next,选择保存此文件的目录并点击Create,即完成了一个Playground的创建:
创建出来的Playground实际上是一个以.playground为后缀的文件,我们知道Playground是Xcode内置的一个程序,当你安装了Xcode之后,Playground就已经内置其中。
在Swift中我们分别用let、var来声明常量和变量,而且Swift中允许使用任何Unicode字符作为变量和常量的名字,甚至包括不属于ASCII编码的字符,例如:中文(var 哈哈=”value”)。
let 常量名:类型 = 表达式
其中的:类型指的是数据类型,是可选的(即可有可没有,有的时候为显式声明,没有的时候则为推断声明)。此外,常量的声明还可以是元组的形式,但元组中的每一项都必须进行初始化:
let (firstNumber,secondNumber) = (10,10)
常量可以用static修饰,这样的常量成为静态常量。
var 常量名:类型 = 表达式
与常量一样,声明中的:类型指的是数据类型,是可选的。但与常量不同的是,变量声明中的初始化也是可选的。而且当变量声明中没有初始化是,必须声明其数据类型。
变量可以被声明为:
var 变量名:type{
get{
语句
}
set(setter name){
语句
}
}
在这种情况下,我们称这种变量为计算型变量,变量的值有get/set方法中的语句决定。
分号
在Swift中,虽然“;”分号仍然是语句结束符,但在Swift并非必须的,因为换行即可表示语句的结束,只有当需要在同一行中写多个语句时,分号才是必须的。
字符串
相较于Objective-C,Swift中的字符串去掉了“@”前缀:
var name = "Microle"
而且对比字符串的方法无需使用isEqualToString方法,而直接用“==”进行对比:
if(name == "Who"){
......
}
向字符串中插入值和运算:
我们使用表达式“(表达式)”这样的占位符来实现插入字符串的功能,插入的内容是表达式的计算结果:
let x=3
let message = "\(x)乘以2.5等于\(Double(x)*2.5)"
字符串的连接操作,我们使用“+”和“+=”运算符来实现:
var s = "hello"
s += "world"
通常我们需要计算字符串的长度,在Swift中我们使用countElements。如果需要一个Objective-C中NSString的length属性一样的长度,则需要使用bridgeToObjectiveC方法:
println("\(string.bridgeToObjectiveC().length)")
1) 数值类型
Swift中常见的数据类型有:整型、Double和Float
var radius:Int = 1
var radius = 1
以上两个语句声明的结果都是相同的,第一句中在声明时就指定变量类型的方式称为显式方式,而在第二句中虽然没有指定变量数据类型,但是编译器在编译时通过变量所赋值的数据类型来推断变量的类型,编译器的这种行为称为“类型推断”。应该尽量使用类型推断的方式来声明常量或者变量,这样可以让代码更为整洁。
整型数据有一系列的精度:8位有符号整型Int8、8位无符号整型UInt8等。使用Int来声明变量,即为不指定其具体精度,由编译器根据具体赋值情况决定其精度。
var a = 3.14
var b:Float = 3.5
var a = 1_000_000
var b = true
在其他编程语言中,可以把非0的值当做true,把0当做false,但是在Swift中不能用整数来对Bool类型赋值。同时,在需要用布尔值控制流程的地方,也不能用整数来代替。
区间
定义了某种有序类型的子集,在Swift中区间分为两种:半闭区间和全闭区间。
半闭区间:使用..<符号定义:var range = 1..<5
,表示从1到5(不包括5)的一系列循序递增的整数。等同于:var range = Range(start:1,end:5)
;
全闭区间使用…符号定义:var range = 1...5
,相较于半闭区间,全闭区间包括了5;
区间常用于流程控制语句中,例如for in和switch中。
元组(tuple)
是Swift中的一种特殊的数据类型,类似与字典,把多个值存储在一起,然后通过索引或者键的方式可以访问元组中的每个值。不同于与字典的是,元组中的值可以是任意类型,并不要求必须是相同类型。
声明元组:let iata_pek = {"PEK","北京国际机场"}
,访问元组成员的方法可以通过“.元素所在的索引”,例如:iata_pek.0
或iata_pek.1
元组也可以更加字典化地声明:let iata_pek = {code:"PEK",airport:"北京国际机场"}
,此时可以通过“.成员名”的方式访问成员:iata_pek.code
元组分解:可以说分解就是元组声明的逆过程,将元组中的元素拆分成多个变量,这样方便对其成员的访问:let (code,airport) = iata_pek
,那么获取成员变量就变成:println("编码:\(code),机场:\(airport)")
,在分解时可以用下划线忽略元组中的某部分成员:let (_,airport) = iata_pek
2). 类型转换
在 Swift中,操作符也是函数的一种,例如“ * ”乘法操作,假如是Double类型数据的乘法操作,实际上就是调用了Double类中的“ * ” 方法:
func *(lhs:Double,rhs:Double) -> Double
所以Swift中不支持不同类型数据的直接相乘,在Objective-C中这种类型转换是自动的,而在Swift中这种隐式转换已经被取消了。所以程序员需要使用到显式的类型转换:
var area = Double(radius)*Double(radius)*pi
此外,Swift还提供了溢出检查,如Int的“自溢式”赋值:Int.max
这是Int的上限值。
在Swift中提供的流程控制结构包括:for、while/do while、if/if else和swicth,以及跳转使用的break和continue。此外,Swift中还加入了for-in循环,而且Swift中的switch无须写break,因此无论如何都不会发生case贯穿的行为。
for var index = 0; index < 3;index ++{
...
}
另一种是快速迭代的for in循环,通常用于快速迭代数组和字典:
let animals = ["tiger","lion","leopad"]
for animal in animals{
println("\(animal)")
}
其中的变量animal你不用声明,因为其是隐式声明的,且不能再循环体之外使用。for in循环甚至还可以变量字典中的键和值:
for (key,value) in dictionary{
println("key:\(key),value:\(value)")
}
for in循环还可以对字符串进行迭代,相当于将字符串中的字符逐个取出:
for character in "HelloWorld"{
...
}
当迭代变量在循环中不会被使用到,可以用下划线来代替:
for _ in animals{
...
}
while a<5 {
...
}
//或者
do{
...
}while a<5
if 语句
Swift中的if语句有多种形式,例如:if、if..else、if…else if…else等。与Objective-C对比的区别就是少了条件表达式的括号,但是在Swift中的{}大括号不允许省略。
switch语句
Swift中的switch最突出的特点是每个case之后的break语句可以省略,因为每次进入switch中只会执行一个case然后就退出switch流程,不存在多个case贯穿执行的情况,正因为这样,所以有两点在Swift中要特别注意的:一是,Swift中的每个分支至少得有一条语句,即不能多个case公用一条语句,否则编译器会报错;二是,default分支是必须的,若不想在default中自行处理,可以直接加上break语句。
此外,Swift中的switch除了匹配简单的整型数据之外,还能匹配浮点数:
let i = 3.14159
switch i{
case 3.14159:
println("\(i):是圆周率")
case 1.41421:
println("\(i):是圆周率")
default:
println("\(i):不明白是什么意思")
}
合并分支:当有多个分支其实进行的是相同的处理时,我们可以将这些分支进行合并:
let i = 19
switch i%9 {
case 1,2,3:
println("\(i)分在第一组")
case 4,5,6:
println("\(i)分在第二组")
default:
println("\(i)分在第三组")
}
匹配区间:跟分支合并相似,只是把匹配条件换成区间
let i = 19
switch i%9 {
case 1...3:
println("\(i)分在第一组")
case 4...6:
println("\(i)分在第二组")
default:
println("\(i)分在第三组")
}
除了意思的匹配类型外,switch还可以匹配字符串和单个字符,甚至可以匹配元组:
let some = (1,1)
switch some {
case (0,0):
println("位于原点")
case (_,0):
println("(\(some.0),0)位于X轴上")
case (0,_):
println("(0,\(some.1))位于y轴上")
case (-2...2,-2...2):
println("(\(some.0),\(some.1))位于矩形之内")
default:
println("(\(some.0),\(some.1))位于矩形之外")
}
值绑定,将上例中的下划线代替为值绑定:
let some = (1,1)
switch some {
case (0,0):
println("位于原点")
case (let x,0):
println("(\(x),0)位于X轴上")
case (0,let y):
println("(0,\(y))位于y轴上")
case (-2...2,-2...2):
println("(\(some.0),\(some.1))位于矩形之内")
default:
println("(\(some.0),\(some.1))位于矩形之外")
}
case let (x,y) where abs(x)==abs(y):
println("(\(x),\(y))位于对角线")