Swift 学习笔记
学习资源:https://doc.swiftgg.team/documentation/the-swift-programming-language
使用 MarkDown 编写列表时,不要把列表中途断开,比如在列表中插入代码块,一定要插到列表里,否则会中断列表
或许现在学这些东西没啥用了
基础知识
变量
- let 声明常量,var 声明变量,let a: Int
- Swift 是明确类型的语言,每一个变量都必须有明确的类型,但 Swift 具有类型推断的机制,在变量声明时可以根据赋值来确定变量类型,因此在赋值类型明确时,可以不用显式说明类型,但若出现无法推断出类型的情况,例如不赋初值时,则必须指定类型
- 逗号分隔连续的变量声明后添加类型注解,这一行变量都是这个类型
1
let a, b, c: Double // abc 都是 Double 类型
- Swift 允许关键字用作变量、函数名,只需要用``包裹变量名即可
- Swift 引用变/常量前,必须初始化,但可以不在定义时初始化
1
let `let` = 2
- 字符串插值使用"\()"
1
let stringInsert = "This is a value: \(value)"
- 在 Swift 中,数值通过加 0、_来提升可读性
1
2let a = 000012_0000 // 实际值为 120000
let b = 000120_0001 // 实际值为 1200001 - 在 Swift 中,可以使用 _
来作为匿名元素的占位符,该元素只允许声明,不允许被引用,_变量可重复被定义
1
let _ = thisIsAFunction()
- 注意:同类型整数相加,即使溢出也不会自动升级类型,永远保持加数的类型
1
2
3let veryBig = UInt8.max + UInt8.max // 猜猜这句对不对
// 实际上是不对的,因为溢出了,即使溢出也不会自动升级类型
// 注意:只有同类型的变量才可进行运算。 - 注意:只有同类型的变量才可进行运算。Int 都不能加
Int8
1
2let a = Int.min + Int8.max // 没错这都不能加
let b = 9 + 1.1 // 这是可以加的,字面量没有类型一说,b 会被推断为 Double - 类型转换的本质就是某个类型的初始化器(构造方法
init()),对于基本类型:Int、Double
等也是结构体类型,也具有一些属性和初始化器
1
let c = Int(1.1) // c = 1
- 使用
typealias关键字来为类型定义别名1
typealias A = Int
- 元组,一种集合类型,允许包含不同类型的元素
- 定义方法
let tup = (1, "2", 3.0) - 在定义时可以为每个元素命名
let tup_ = (intElem: 1, stringElem: "2") - 可以通过索引引用(从 0
开始),也可以通过元素名称引用
let a = tup.0,let b = tup.intElem - 你甚至可以一次性将元组值赋给一组变量
let (q, w, e) = tup - 元组可以嵌套
let p = (1, (2,), (3, 4), 5)
- 定义方法
- 和 Java 一样,Swift 支持函数重载,支持不同参数列表的相同函数名的函数
- guard 语句,是一种流程控制语句,作用在于守门,用于实现
“在不满足要求时” 提前退出
- 语法
guard a == 0 else {条件不成立时执行的语句} - guard 没有条件成立时执行的语句,只有条件不成立时执行的语句块,且 Swift 强制要求 guard else {} 语句块中必须包含结束类语句,例如 return 。
- guard 作用在于守门,当条件不成立时,其后续的语句将不再执行,直接返回。
- 用 guard 处理异常条件,用 if 处理正常逻辑判断。
- 语法
Optional 可选类型
这个地方和 Java 完全不同
Swift 中也有代表值为空的关键字,即
nil但对于非可选类型的变量,其值不允许为
nil,也就是说,Swift 不允许非可选变量为空只有可选类型的变量才可为
nil,可选类型变量的值要么是具体的一个值,要么为nil非可选类型变量可以赋值给可选类型变量,会自动转化(但是 Float 却没办法自动转化为 Double)
定义:
let opt: Int? = nil只需要在基本类型后加个?即代表可选类型一个很典型的例子,使用 Int(String) 初始化器将字符串转换为数字时,该初始化器返回的便是
Int?可选类型,因为字符串并不一定可以转化为数字,当无法转换为数字时便会返回nil。要注意,即使可选类型的变量,其值不为
nil,即包含具体值,该变量也不可当做非可选变量去直接进行运算。即 可选类型变量不可当做非可选类型变量去直接使用。在使用之前,需要先进行解包。例如上一条中,Int(String) 初始化器返回的不是 Int 类型,而是 Int? 类型,或者说是 Optional<Int> 类型,该类型不可参与 Int 间的运算,必须先进行解包,解包成功后会成为非可选的 Int 类型。Optional 类型不可以赋值给 non-Optional 类型,不会自动解包 ### 解包方法
使用 '!' 强制解包,但不推荐。
let optd = opt!,当 opt 为nil时,解包失败,此时会抛出运行时错误,中断程序运行,因此只能在确定 100% 非空时才可用。可选绑定是更安全的解包方法。
if/guard/while let/var optd = optif
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17// if let
if let optd = opt {
// 解包成功执行
// 注意,optd 变量只在解包成功的 if 语句块内有效,出了 if 就不存在这个变量了
} else {
// 解包失败执行
}
// 可选绑定创建的新变量名称可以和原可选变量名称相同
if let opt = opt {
// 解包成功执行,此时非可选的普通变量名称也是 opt,会覆盖原可选,在 if 语句块内,原可选变量无法再次访问
}
// 最后你可以简写成这样
if let opt {
// 解包成功执行,opt 为解包后的非可选变量
}
// 通过可选绑定解包后,解包得到临时的非可选变量。如果要更改该变量,则可以使用 if var。
// 但修改仅会影响解包后得到的临时变量,不会影响原可选在 if 进行可选绑定时,其得到的解包后的非可选类型变量,只在 if 语句块内有效。如果想实现后续代码中都有效,则可以考虑使用 guard
1
2
3
4
5
6
7
8
9// guard let
guard let optd = opt else{
return // guard else 语句块内必须包含退出语句,该句在解包失败时会直接返回
}
// 后续语句中,optd 都有效,为非可选类型
guard let opt else{
return
}
// 后续语句中,opt 将变换为非可选类型,原可选类型被覆盖,不可再访问可选绑定解包可以连续解多个包,用
,隔开即可if let a, let b, ...,其中只要有一个解包失败,就会进入 else 块
通过提供后备值进行解包
let optd = opt ?? 2该句提供了 2 这个后备值,当 opt 不可解包时,optd 就会被赋值为 2。当 opt 可解包时,optd 就会被赋值为 opt 的实际值。隐式解包可选类型
- 隐式解包可选类型 本质上仍是 可选类型,但在引用时可以作为普通变量使用
- 在引用隐式可选类型时,Swift 会先将其作为可选类型,若无法作为可选类型(例如赋值给一个普通变量),则会对其进行强制解包,然后将其作为非可选类型。若解包失败,则会抛出运行时错误。
- 定义:
let hideOpt: Int! = 2