美文网首页
【Swift】可选类型(Optional)

【Swift】可选类型(Optional)

作者: 小雪球大梦想 | 来源:发表于2022-12-25 15:41 被阅读0次

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,否则会触发运行时报错。

相关文章

网友评论

      本文标题:【Swift】可选类型(Optional)

      本文链接:https://www.haomeiwen.com/subject/wmuwqdtx.html