Swift5.1-可选项

87 阅读4分钟

可选项

定义

  • 可选项,也称为可选类型,它允许将值设置为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 来查看区别。