【Swift】可选类型(Optional)

Optional是Swift中的一个枚举类型,用于表示值可能存在或缺失。它有两种状态:some(Wrapped)存储一个值,none则表示值缺失(相当于nil)。在使用时,我们可以通过可选绑定(iflet,guardlet,switch)、可选链、空合运算符和无条件解包来安全地处理Optional值。安全解包确保在值不存在时不触发运行时错误,提供了一种优雅的方式来处理可能为nil的情况。
摘要由CSDN通过智能技术生成

Optional是什么?

A type that represents either a wrapped value or nil, the absence of a value.

我们从官方文档关于Optional介绍可以看出,可选类型Optional可以是包装值,也可以是nil,也就是缺失值。有且仅有这两种情况。

You use the Optional type whenever you use optional values, even if you never type the word Optional. Swift’s type system usually shows the wrapped type’s name with a trailing question mark (?) instead of showing the full type name. For example, if a variable has the type Int?, that’s just another way of writing Optional<Int>. The shortened form is preferred for ease of reading and writing code.

在平时的代码编程过程中,我们似乎没有见过Optional这个单词。以Int为例,Optional<Int>是它的一种写法,还有一种是Int?

// shortForm和longForm是等同的。
let shortForm: Int? = Int("42")
let longForm: Optional<Int> = Int("42")

Optional<Int>Int?是等同的。所以Optional可以理解为是?

The Optional type is an enumeration with two cases. Optional.none is equivalent to the nil literal. Optional.some(Wrapped) stores a wrapped value.

Optional是一个枚举类型,它包含两个casenoneOptional.some(Wrapped)

接下来,我们看看Optional的代码。

@frozen public enum Optional<Wrapped> : ExpressibleByNilLiteral {

    /// The absence of a value.
    ///
    /// In code, the absence of a value is typically written using the `nil`
    /// literal rather than the explicit `.none` enumeration case.
    case none

    /// The presence of a value, stored as `Wrapped`.
    case some(Wrapped)

// For example:
let number: Int? = Optional.some(42)
let noNumber: Int? = Optional.none
print(noNumber == nil)// Prints "true"

从官方代码看到,Optional是一个enum枚举,里面有两个casenonesome(Wrapped)Optional.none就是nilOptional.some(Wrapped)就是一个包装值,Wrapped 就是存储的值。

安全解包

You must unwrap the value of an Optional instance before you can use it in many contexts. Because Swift provides several ways to safely unwrap optional values, you can choose the one that helps you write clear, concise code.

如果值被Optional包装,取值时需要打开包装,官方提供了几种安全解包的方法。

我们以下面的字典为例,来介绍安全解包的几种方式:

let imagePaths = ["star": "/glyphs/star.png",
                  "portrait": "/images/content/portrait.jpg",
                  "spacer": "/images/shared/spacer.gif"]

通过字典的key值获取value值,这个返回的value值就是一个Optional值,所以imagePaths["star"]Optional<String>类型,我们也可以写成String?

1. 可选绑定(Optional Binding)

To conditionally bind the wrapped value of an Optional instance to a new variable, use one of the optional binding control structures, including
if let, guard let, and switch.

// if let, 打印 [if let] The star image is at '/glyphs/star.png'
if let starPathIf = imagePaths["star"] {
    print("[if let] The star image is at '\(starPathIf)'")
}

// guard let, 打印 [guard let] The star image is at '/glyphs/star.png'
func guardTest() {
    guard let starPathGuard = imagePaths["star"] else {
        return
    }
    print("[guard let] The star image is at '\(starPathGuard)'")
}
guardTest()

// switch, 打印 [switch] The star image is at '/glyphs/star.png'
switch imagePaths["star"] {
case .none:
    print("nil")
case .some(let starSwitch):
    print("[switch] The star image is at '\(starSwitch)'")
}

2. 可选链(Optional Chaining)

To safely access the properties and methods of a wrapped instance, use the postfix optional chaining operator (postfix ?).

if imagePaths["star"]?.hasSuffix(".png") == true {
    print("The star image is in PNG format")
}
// Prints "The star image is in PNG format"

imagePaths["star"]取出来的值为Optional值。为了安全访问imagePaths["star"]包装值的属性或方法,我们需要在imagePaths["star"]后面添加?,即imagePaths["star"]?

当值为nil的时候,不满足继续执行的条件,所以hasSuffix(".png")就不会被调用。
当值为String的时候,继续执行,所以hasSuffix(".png")就会被调用。

3. 空合运算符(Nil-Coalescing Operator)

Use the nil-coalescing operator (??) to supply a default value in case the Optional instance is nil. Here a default path is supplied for an image that is missing from imagePaths.

当可选实例的值为nil时,给可选实例一个默认值。

let defaultImagePath = "/images/default.png"
let heartPath = imagePaths["heart"] ?? defaultImagePath
print(heartPath)
// Prints "/images/default.png"

The ?? operator also works with another Optional instance on the right-hand side. As a result, you can chain multiple ?? operators together.

默认值也可以是可选实例。

let shapePath = imagePaths["cir"] ?? imagePaths["squ"] ?? defaultImagePath
print(shapePath)
// Prints "/images/default.png"

4. 无条件解包(Unconditional Unwrapping)

When you’re certain that an instance of Optional contains a value, you can unconditionally unwrap the value by using the forced unwrap operator (postfix !).

强制取出包装内的值。

let number = Int("42")!
print(number)
// Prints "42"

You can also perform unconditional optional chaining by using the postfix ! operator.

无条件解包也可以用于可选链。

let isPNG = imagePaths["star"]!.hasSuffix(".png")
print(isPNG)
// Prints "true"

Unconditionally unwrapping a nil instance with ! triggers a runtime error.

无条件解包之前得确定解包的可选实例值不能为nil,否则会触发运行时报错。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值