13.可选链

70 阅读2分钟

可选链

可选链的基本概念

可选链(Optional Chaining)是Swift中一种安全访问可选值的方式,它允许你查询和调用可选值的属性、方法和下标,而不需要显式地解包可选值。 说说我自己对可选链的理解:可选链其实就是可以用一连串的?,如果?前的值为nil,那么这个表达式的执行结果就是nil,不往下执行了。其实和js中基本一样的。还有可选链的返回的一定是可选类型,因为有返回nil 的这种情况,非可选类型不能放nil.

基本特性

  • 如果可选项为nil,调用方法、下标、属性失败,结果为nil
  • 如果可选项不为nil,调用方法、下标、属性成功,结果会被包装成可选项
  • 如果结果本来就是可选项,不会进行再次包装

可选链的语法

基本语法

// 使用问号(?)进行可选链调用
optionalValue?.property
optionalValue?.method()
optionalValue?[index]

与强制解包的对比

// 强制解包(危险)
let result = optionalValue!.property

// 可选链(安全)
let result = optionalValue?.property

可选链的工作原理

基础示例

class Car { 
    var price = 0 
}

class Dog { 
    var weight = 0 
}

class Person {
    var name: String = ""
    var dog: Dog = Dog()
    var car: Car? = Car()
    
    func age() -> Int { 
        return 18 
    }
    
    func eat() { 
        print("Person eat") 
    }
    
    subscript(index: Int) -> Int { 
        return index 
    }
}

var person: Person? = Person()

方法调用

let age1 = person!.age()  // Int (强制解包)
let age2 = person?.age()  // Int? (可选链)

属性访问

let name = person?.name   // String?

下标访问

let index = person?[6]    // Int?

延迟执行特性

func getName() -> String { 
    return "jack" 
}

// 如果person是nil,不会调用getName()
person?.name = getName()

方法调用结果

if let _ = person?.eat() { // ()?
    print("eat调用成功")
} else {
    print("eat调用失败")
}

可选链的使用场景

1. 嵌套可选值访问

var dog = person?.dog       // Dog?
var weight = person?.dog.weight  // Int?
var price = person?.car?.price   // Int?

2. 多级可选链

多个?可以链接在一起,如果链中任何一个节点是nil,那么整个链就会调用失败。

class Address {
    var street: String?
    var city: String?
}

class Person {
    var address: Address?
}

class Company {
    var manager: Person?
}

let company: Company? = Company()
let street = company?.manager?.address?.street  // String?

3. 数组和字典的可选链

var scores = ["Jack": [86, 82, 84], "Rose": [79, 94, 81]]

// 安全地访问和修改数组元素
scores["Jack"]?[0] = 100
scores["Rose"]?[2] += 10
scores["Kate"]?[0] = 88  // Kate不存在,操作被忽略

print(scores)
// ["Jack": [100, 82, 84], "Rose": [79, 94, 91]]

4. 可选值的赋值

var num1: Int? = 5
num1? = 10  // Optional(10)

var num2: Int? = nil
num2? = 10  // nil (没有被赋值)

5. 函数可选链

var dict: [String: (Int, Int) -> Int] = [
    "sum": (+),
    "difference": (-)
]

let result = dict["sum"]?(10, 20)  // Optional(30), Int?
let result2 = dict["multiply"]?(10, 20)  // nil