本文介绍 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 |
|