可选项
定义
- 可选项,也称为可选类型,它允许将值设置为nil。
- 在类型名称后面加一个? 来定义一个可选项。
// 例子1
var num: Int? = 10
num = nil
// 例子2
let array = [10, 20, 30]
func get(_ index: Int) -> Int? {
if index < 0 || index >= array.count {
return nil
}
return array[index]
}
强制解包
可选项是其他类型的一层包装。可以理解为一个空盒子。
- 如果为nil, 则可以理解为空盒子
- 不为nil, 则可以理解为盒子里装的是:被包装类型的数据
要想从可选项中取出被包装的数据,则需要使用感叹号!进行强制解包。
var age: Int? = 10
var ageInt: Int = age! //进行强制解包
ageInt += 10
注意: 如果对空的可选项进行强制解包,会报运行时错误。
var age: Int? = nil
age! // 会报错
可选项绑定
可以使用可选项绑定来判断一个可选项是否包含值。
- 如果包含值就会进行自动解包,将值赋值给一个临时的常量(
let
)或者 变量(var
),并返回true, 否则返回false。
if let num = Int("123") {
print(num)
} else {
print("可选项绑定失败")
}
可选项的并运行符
if let num1 = Int("4") {
if num2 = Int("2") {
if num1 > num2 && num2 > 1 {
print(num1)
}
}
}
if let num1 = Int("4"),
let num2 = Int("2"),
num1 > num2 && num2 > 1 {
print(num1)
}
上面两种写法是等价的。
空合并运算符 ??
a ?? b
- a 是可选项。
- b 是可选项和非可选项都可以。
- a 和 b 的存储类型必须相同。
- 如果 a 不为nil, 则直接返回a。
- 如果 a 为nil, 则返回b。
- 如果 b 是非可选项,在返回a 时需要对a进行强制解包。
var a: Int? = 1
var b: Int? = 2
var c = a ?? b // Option(1), c 是可选项
var a: Int? = nil
var b: Int? = 2
var c = a ?? b // Option(2), c 是可选项
var a: Int? = nil
var b: Int? = nil
var c = a ?? b // nil, c 是可选项
var a: Int? = nil
var b: Int = 2
var c = a ?? b // 2, c 是非可选项
var a: Int? = 2
var b: Int = 1
var c = a ?? b // 2, c 是非可选项
var a: Int? = 1
var b: Int? = 2
var c = a ?? b ?? 3 // 1, c 是非可选项
?? 和 if let配合使用
var a: Int? = nil
let b: Int?= 2
if let c = a ?? b {
print(c)
}
// 等价于 if a != nil || b != nil {}
guard 语句
guard
语句适合用来做提前退出。
guard 条件 else {
// 退出当前作用域 return\break\continue\throw error
}
- 当
guard
语句条件为true时,跳过大括号,执行后面的语句。 - 当
guard
语句条件为false时,会进入大括号, 执行大括号里的内容。 - 当使用
guard
语句进行可选项绑定时,绑定的临时常量或者变量 能在外层作用域内使用。
func login(_ info[String, String]) {
guard let username = info["username"] else {
print("请输入用户名")
return
}
print("用户名为:\(username)")
}
隐式解包(Implicitly Unwrapped Optional)
在某些情况下,可选项一旦被赋值,就会一直有值。 在这种情况下可以去掉检查,不必每次访问时都进行解包,因为它每次访问的时候都有值。可以在类型后面加一个感叹号!
,定义一个隐式解包的可选项。
let num1: Int! = 10
let num2: Int = num1 // 进行了隐式解包
if num1 != nil {
}
if let num = num1 { // num1 是可选类型,可进行可选项绑定
}
- 注意: 当隐式解包可选项值为nil,使用时会报错。
var num1: Int! = nil
var num2: Int = num1 // 隐式解包报错 Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value
字符串插值
可选项在字符串插值或者直接打印时,会出现警告。
var age: Int? = 10
print("your age is \(age)") // 会有警告~
消除警告的三种方法:
var age: Int? = 10
print("your age is \(age!)") // 强制解包
print("your age is \(String(describing:age))")
print("your age is \(age ?? 0))") //空合并运算符
多重可选项
// 例子1
var num1: Int? = 10
var num2: Int?? = num1
var num3: Int?? = 10
if (num2 == num3) // true
// 例子2
var num1: Int? = nil
var num2: Int?? = num1
var num3: Int?? = nil
if (num2 == num3) // false
// 理解: num2 是有值的,值为num1, 但是num3的值为nil。
if (num1 == num3) // false ,原因:类型不相同。
可以使用lldb指令 frame variable -R
或者 fr v -R
来查看区别。