Swift基础
本文介绍Swift语言的基础内容,主要包括数据类型、流程控制、集合类型、函数和闭包等。
数据类型
基本数据类型
Swift包含了C和Objective-C上所有的基础数据类型:
- Int:整数,无符号类型使用UInt。在32位平台上,Int与Int32长度相同;在64位平台上,Int与Int64长度相同
- Float:32位浮点数
- Double:64位浮点数
- Bool:布尔值
- Character:字符
- String:字符串,是字符的集合
字符串是我们平常开发中频繁使用的数据类型,Swift也给字符串封装了相当多的功能。常见的比如字符串插值:
1
2let a = "gcfeng"
let s = "hello \(a)" // 输出:hello gcfengfor-in
循环来遍历字符串的每一个字符:
1
2
3for c in s {
print(c)
}
常量与变量
如果熟悉TypeScript,会发现两者声明变量的方式很像。不同的是,Swift中使用let
来定义常量,使用var
来定义变量。
1
2
3
4
5
6
7
8// 使用let来声明常量,使用var来声明变量
let s: String = "hello"
// Swift支持类型推断,这里推断出v是整型。类型推断可以在声明变量时省略类型声明
var v = 10
// Swift是类型安全的,v是整型,这里将字符串赋值给整型变量会报错
v = "error"
元组
除了上面基础的数据类型,Swift还增加了元组。元组将多个值组合成了一个复合值。元组内的值可以是任意类型,比如(200, "OK")
是一个被描述为(Int, String)
类型的元组。元组在函数有多个返回值时会非常有用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14// 声明一个元组
let httpCode = (200, "OK")
// 解构赋值,与ES类似
let (status, code) = httpCode
// 可以通过下标来访问元组的值
print(httpCode.0)
print(httpCode.1)
// 也可以定义命名元组
let namedHttpCode = (status: 200, code: "OK")
print(namedHttpCode.status)
print(namedHttpCode.code)
可空类型
可空类型(optional)用来指定某个实例要么有值可用,要么没有值为nil。在Objective-C中,nil表示一个指向不存在对象的指针,然而在Swift中,nil是一个确定的值。
1
2
3
4
5
6
7
8
9
10
11// 声明可空类型。这里没有赋值,默认就是nil
var str: String?
str = "hello"
// 如果我们确定str有值,可以使用!强制展开,否则会报错
let val = str!
// 使用if语句来展开,如果str为nil,不会进入到条件语句内部
if let val = str {
print(val)
}!
。这种方式定义的可空类型与普通的相比只是不需要展开。通常这种方式只在类的初始化中使用。
1
2
3
4
5
6
7var str: String!
// str为nil,直接赋值给str2会报错
let str2: String = str
// str3的类型会演变为String?
let str3 = str1
2
3
4
5
6
7
8
9
10let str: String?
let str2: String
if let v = str {
str2 = v
} else {
str2 = "defualt value"
}
// 可以使用下面这条语句来完成上面的功能
let str2 = str ?? "default value"
流程控制
Swift语言提供的流程控制语句大多与其他语言类似,不再赘述。这里只是列出一些值得注意的地方。首先Swift语言中的判断语句和循环语句都需要带上花括号:
1
2
3if someValue > 1 {
print("ok")
}for-in
循环可以遍历数字范围:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20// 遍历1到5
for index in 1...5 {
print("\(index)")
}
// 如果我们不需要区间序列内的值,可以使用下划线来代替
for _ in 1...5 {
print("\(index)")
}
// 同时另外的区间运算符也是支持的
// 遍历1到4
for index in 1..<5 {
print("\(index)")
}
// 假设names是一个数组,这里从names的第二项开始遍历
for name in names[2...] {
print("\(name)")
}switch
语句做了增强,case
子句可以匹配多种不同模式:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28let statusCode = 400
let errorString = "The request failed."
// 注意到每一个case子句没有写break,当匹配到一个case子句时,Swift默认执行完就会跳出
switch statusCode {
case 100, 101:
errorString += " Informational, 1xx."
// case子句支持区间运算符
case 300...307:
errorString += " Redirection, 3xx."
// case子句支持值匹配,将statusCode赋值给unknowCode
case let unknownCode:
// unknownCode常量只能在该分支中使用
errorString += "\(unknownCode) is not a known error code."
}
// 这里是更加复杂的情景
switch statusCode {
case 100, 101:
errorString += " Informational, 1xx."
case 300...307:
errorString += " Redirection, 3xx."
// 使用where子句
case let unknownCode where (unknownCode >= 200 && unknownCode < 300) || unknownCode > 505:
// unknownCode常量只能在该分支中使用
errorString += "\(unknownCode) is not a known error code."
default:
errorString = "Unexpected error"
}
集合类型
Swift语言提供了数组(Array)、集合(Set)和字典(Dictionary)三种基本的集合类型。
1 | // 数组 |
函数
作为现代语言,Swift的函数语法非常灵活。
1 | // sayHello1函数定义了一个函数参数,其中to为外部参数,name为内部参数, |
闭包
闭包是自包含的函数代码块,是一种引用类型,可以在代码中被传递和引用。闭包可以捕获和存储其所在上下文中任意常量和变量的引用。闭包表达式的一般语法为:
1
2
3{(params) -> return type in
// body
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19// 先定义一个数组
let numbers = [1, 3, 40, 5, 10]
// 写法1
let numbersSorted = numbers.sorted(by: {
(i: Int, j: Int) -> Bool in
return i < j
})
// 写法2:利用类型推断系统来简化代码
let numbersSorted = numbers.sorted(by: { i, j in i < j })
// 写法3:编译器的类型推断可以知道闭包接受的参数个数和类型,这意味着不需要给参数命名
// 使用$0引用第一个参数值,$1引用第二个参数值
let numbersSorted = numbers.sorted(by: { $0 < $1 })
// 写法4:如果一个闭包是以一个函数的最后一个参数传递的,那么它就可以在函数的圆括号以外内联。
// 这种方式也叫做尾随闭包优化。
let numbersSorted = numbers.sorted { $0 < $1 }