本文介绍 Swift 语言的基础内容, 面向已经熟练掌握某项开发语言的开发者, 因此内容力求简洁. "Swift 快速入门" 上篇包括常用的数据类型、控制语句、函数, 以及 Swift 特有的闭包语法. 下篇将介绍 Swift 的结构体、类与继承以及协议等内容.
1. 基础
Swift 是一门强类型语言,使用关键字 var
定义变量, let 定义常量.
数据类型
常用的数据类型有:
- 整形
Int, 默认为Int64.Int16相当于short, 2 字节, [-32768, 32767].Int32相当于int, 4 字节, [-2147483648, 2147483647].Int64相当于long, 8 字节, [-9223372036854775808, 9223372036854775807].
- 字符串
Sting, 使用双引号定义字面量.使用三双引号可以换行, 但使用三引号时需另起一行.
使用
\(variable)语法定义模版字符串1
2
3
4
5
6
7let to = "world"
var greeting = "Hello, \(to)!"
var gretting2 =
"""
Hello
\(to)
"""
Double, 双精度浮点数Bool,true/false
类型推断
Swift 在定义变量时会进行类型推断. 也可以通过
variable: Type 的语法显示指定类型:
1 | |
查看类型
通过函数 type(of: variable) 查看 variable
的类型.
1 | |
2. 复杂数据类型
数组 Array
声明数组变量:
1 | |
数组访问不能越界, 否则会报错.
Swift 会自动推断数组类型,但当数组中有不同类型元素时要显式声明类型.
例如使用 Any 类型 (Any
是一种特殊的类型,可以表示任何类型):
1 | |
只是声明数组变量并不会实际创建它:
1 | |
使用下面两种语法,则会被立即创建:
1 | |
集合 Set
无顺序, 不重复. 但可以被迭代. 可以通过 contains
判断某个元素是否在集合中.
1 | |
元组
- 顺序固定.
- 一旦定义, 不可增删.
- 但可以通过
.操作符来修改.
1 | |
字典 Dictionary
1 | |
访问不存在的键时,返回 nil,也可设置默认值:
1 | |
创建空字典时需要显示指定数据类型, 然后再添加条目
1 | |
枚举 Enum
和很多语言中的枚举类型类似, 在 Swift 中枚举类型没有特别的含义, 但使用它可以使得编码更加安全高效.
1 | |
可以使用简略语法:
1 | |
可以为枚举类型设置关联属性,以方便的适应一些场景
1 | |
当指定枚举值为 Int 类型时, Swift 会为枚举值从
0 开始自动设置原始值, 此时可以通过
rawValue 定义一个枚举值.
1 | |
也可以手动设置枚举值的原始值,
1 | |
补充和小结
不同于数组、集合、字典, Swift 中元组是一种匿名数据类型.
Swift 为 Array 和 Dictionary
设置了特殊的语法, 而 Set 没有:
1 | |
除了各自字面量定义语法还支持尖括号的定义语法:
1 | |
3. 运算符和控制语句
运算符
- 可重载,
- 可复合:
+= - 比较运算符:
><>=<=两边必须同类型. ==,!=判等会进行隐式类型转换.&&,||要求两侧都是Bool类型.
和 Python 类似, 数组可以通过 +
拼接.
条件语句
1 | |
三元运算符
[cdt] ? [exp] : [exp]
Swift 有和 C 语言类似的三元运算符语法
switch 语句
Swift 的 switch 语句中各个 case 默认是自动结束的, 因此不需要
break, 相反当需要继续执行时需要 fallthrough.
1 | |
switch 要确保覆盖所有场景,因此很多情况下 default 是必须的,但也有例外,比如对于 enum 变量来说,容易穷尽所有 case.
范围运算符 ..<
...
范围运算符会返回 Range<Int>. 例如
1..<4 表示 1, 2, 3, 而 1...4 表示 1, 2, 3,
4.
1 | |
for in 循环
for 循环中的迭代变量为临时变量.
当不使用迭代变量时, 可以用 _ 代替.
1 | |
while 和 repeat while
1 | |
使用 break 结束当前循环, 使用
continue 跳过当前迭代.
为循环语句添加标签可以使用 break label 跳出指定循环.
5. 函数
函数基本语法
1 | |
需要指明形参名和参数类型. 当函数有返回值时要指明返回类型.
使用 return 语句返回, 当函数体只有一行时,
可以省略 return.
和 Python 类似, 可以使用元组返回多个值.
参数标签
除了形式参数名, Swift 还为还为参数添加了标签. 标签用于外部(调用时), 形参名用于内部, 以实现更好的语义化.
1 | |
调用函数时, 需要指明参数标签. 没有定义标签时使用形参名作为标签.
也可以把参数标签指定为 _ 来省略调用时的参数标签:
1 | |
默认参数值
与 C 语言类似的语法指定默认参数值
1 | |
可变参数
在参数类型后添加 ... 使函数可以接受可变数量的参数,
函数体内该参数会被转换为数组. 注意调用时可变参数的写法.
1 | |
可能抛出异常的函数
可能抛出异常的函数要在返回类型前添加关键字 throws.
并在需要抛出异常的地方使用 throw 语句抛出异常.
1 | |
当调用可能会抛出异常的函数时要使用 do try
catch 语句.
1 | |
inout 参数
在 Swift 中, 参数默认都是 let 常量不可被修改.
下面的函数会报错, 因为期望修改 number 的值.
1 | |
如果想要修改参数的值, 需要在定义函数的参数类型前加上关键字
inout. 并且在调用时要在实参变量前加上
&.
1 | |
这么设计的目的其实是要求函数不会对传入的值造成副作用, 除非明确的指明. inout 参数的使用类似于 C 语言的指针.
6. 闭包
函数作为“一等公民”可以被赋值给变量, 并作为参数传递, 称之为闭包. (这与 JavaScript 中闭包的概念并不完全相同)
闭包定义和调
1 | |
对于闭包函数, 定义参数时要使用 in 关键字,
且不可定义参数标签, 调用时也无法使用标签.
1 | |
闭包的返回和函数类似, 只有一行时可以省略 return.
1 | |
闭包作为参数传递
闭包可以作为参数传递. 使用 func 定义的函数也可以.
闭包和函数作为参数传递时, 需要使用形如
(arg1: Int) -> Void 的语法为参数声明类型.
1 | |
尾随闭包语法
这是 Swift 中很独特且又常用的语法形式.
当函数作为最后一个参数时, 可以使用以下语法调用. 即直接使用大括号将要传入的函数以闭包的形式定义.
1 | |
更特别地, 当没有其他参数时可以省略小括号:
1 | |
常见的闭包语法
带参数的闭包作为参数
1
2
3
4
5
6
7
8
9
10func travel(action: (String) -> Void) {
print("I'm getting ready to go")
// 把 London 传入闭包 actiong
action("London")
print("I arrived")
}
travel() {(place: String) in
print("trailing closure syntax with param \(place)")
}有返回值的闭包作为参数
1
2
3
4
5
6
7
8
9
10func travel(action: (String) -> String) {
print("I'm getting ready to go")
let message = action("London")
print(message)
print("I arrived")
}
travel() {(place: String) in
"trailing closure syntax with param \(place)"
}一系列简写语法
当闭包作为参数时, 它的参数被明确, 则定义闭包时可以省略类型
类似
func, 函数体只有一行时可以省略return.1
2
3travel() {place in
"trailing closure syntax with param \(place)"
}参数在声明时类型被明确, 定义时甚至可以直接省略形参, 使用
$[num]代表.1
2
3
4
5
6
7
8func travel(action: (String, Int) -> String) {
print("I'm getting ready to go.")
print(action("London", 60))
print("I arrived")
}
travel {
"I'm goning to \($0) at \($1) miles hour"
}
返回闭包
1 | |
闭包作用域保存
闭包会保存作用域链, 这一点和 JavaScript 类似.
1 | |