Swift 可选类型(Optionals)

在本文中,您将了解可选类型、其用例和 Swift 中的可选处理。

在上一篇文章中,我们了解了 Swift 中可用的不同数据类型,并注意到这些类型的变量或常量包含默认值。

  1. let someValue = Int()
  2. print(someValue)

结果如下:

  1. 0

然而,Swift 中还有另一种称为 Optional 的数据类型,其默认值为空值(nil)。如果希望变量或常量中不包含任何值,则可以使用 optional。可选类型可以有值,也可以没有值(空值)。


如何声明可选类型?

您可以简单地通过在类型后附加 !? 将数据类型表示为可选类型。如果可选类型中有值,则返回值为 Optional<Value>,否则返回 nil

实例 1:如何在 Swift 中声明可选类型?
  1. var someValue:Int?
  2. var someAnotherValue:Int!
  3. print(someValue)
  4. print(someAnotherValue)

结果如下:

  1. nil
  2. nil

在上面的程序中,我们已经使用初始化了可选类型?和这两种方法都可以创建可选类型的,但有一个主要区别,我们将在下面探讨。

声明可选整数意味着变量将具有整数值或没有值。由于没有给变量赋值,所以您可以在屏幕上看到两个 print 语句输出 nil


实例 2:从可选项中赋值和访问值?
  1. let someValue:Int? = 5
  2. print(someValue)
  3. print(someValue!)

结果如下:

  1. Optional(5)
  2. 5

在上面的程序中,我们声明了一个可选的 Int 类型,并在其中赋值 5。

如您所见,print(someValue) 并不会给出 5,而是 Optional(5)。它的形式如上所述:Optional<Value>。为了从中访问 <Value>,我们需要一种称为解包(unwrapping)的机制。

您可以通过在变量/常量末尾附加 ! 字符来解包一个可选类型,如下一行 print(someValue!)print(someValue!) 解包可选类型并在屏幕上输出 5

但是,请记住,只有当您确定在访问可选类型时,该可选类型一定会有值时,才应使用这种解包机制。


实例 3:显式声明解包的可选类型

您还可以创建一个未解包的可选项,如下所示:

  1. let someValue:Int! = 5
  2. print(someValue)

结果如下:

  1. 5

在上述程序中,Int!创建一个解包的可选类型,当您访问该值时,它会自动打开该值,这样您就不需要每次附加 ! 字符。

注意:在使用这些类型的选项时,请确保变量在访问时始终需要有一个值。如果不这样做,将导致致命的错误崩溃。

实例 4:访问解包可选类型时出现致命错误
  1. var someValue:Int!
  2. var unwrappedValue:Int = someValue //crashes due to this line

当您运行程序时,会出现致命错误:在解包可选值时意外发现 nil,因为代码unwrappedValue:Int = someValue 试图将可选 someValue 的值赋给变量 unwrappeValue

但是,somevalue 是包含 nil 值的可选类型。尝试将 nil 值赋值给变量 unwrappedValue(非可选)将导致崩溃。

可以不同的技术来处理这种情况,如下所述。


可选类型处理

为了使用可选类型,需要将其解包。使用可选类型的更好方法是使用条件解包,而不是使用 ! 运算符强制解包。

这是因为有条件解包要求检查此变量是否有值。如果是,请给出值,否则将处理 nil 情况。

相反,强制解包表示在使用该变量时,该变量确实有一个值。因此,当您强制解包一个为 nil 的变量时,您的程序将在展开可选异常和崩溃时抛出意外发现的 nil。条件解包的一些技术解释如下:

1.If 语句

可以使用 if 语句并将 optionalnil 进行比较,以确定 optional 是否有值。您可以在 if 语句中使用比较运算符"等于"运算符(=)或”不等于”运算符(!=)。

实例 5:可选类型处理 if-else 语句
  1. var someValue:Int?
  2. var someAnotherValue:Int! = 0
  3. if someValue != nil {
  4. print("It has some value \(someValue!)")
  5. } else {
  6. print("doesn't contain value")
  7. }
  8. if someAnotherValue != nil {
  9. print("It has some value \(someAnotherValue!)")
  10. } else {
  11. print("doesn't contain value")
  12. }

结果如下:

  1. doesn't contain value
  2. It has some value 0

在上述程序中,如果可选类型有值,则执行 if 语句中的代码,否则执行 else 块中的语句。使用此技术的可选处理的主要缺点是,您仍然需要使用 ! 运算符从可选类型这中解包值。


2.可选绑定(if-let)

可选绑定帮助您确定可选项是否有值。如果可选类型有值,则该值可用作临时常量或变量。因此,可选绑定可以与 if 语句一起使用,以检查可选类型中的值,并在单个操作中将该值提取为常量或变量。

if-let 语句的可选处理" class="reference-link">实例 5:使用 if-let 语句的可选处理
  1. var someValue:Int?
  2. var someAnotherValue:Int! = 0
  3. if let temp = someValue {
  4. print("It has some value \(temp)")
  5. } else {
  6. print("doesn't contain value")
  7. }
  8. if let temp = someAnotherValue {
  9. print("It has some value \(temp)")
  10. } else {
  11. print("doesn't contain value")
  12. }

结果如下:

  1. doesn't contain value
  2. It has some value 0

在上述程序中,如果可选类型有值,则执行 if 语句中的代码。否则执行 elseif let 语句还自动解包,并将解包的值放置在 temp 常量中。这种技术具有主要优势,因为您不需要强制解包值,尽管可以确定可选类型是有值的。


3. Guard 语句

在 Swift 中,您可以使用 guard 来处理可选类型。如果你不知道 guard 是什么,不要担心。现在,只需将 guard 视为一个没有 ifif-else 条件。如果条件失败,则执行 else 语句。如果不是,则执行下一个语句。有关更多详细信息,请参阅 Swift guard。

实例 6:使用 guard let 的可选处理
  1. func testFunction() {
  2. let someValue:Int? = 5
  3. guard let temp = someValue else {
  4. return
  5. }
  6. print("It has some value \(temp)")
  7. }
  8. testFunction()

结果如下:

  1. It has some value 5

在上述程序中,guard 包含一个条件,即可选的 someValue 是否有值。如果它包含一个值,则 guard let 语句将自动解包该值,并将解包的值放置在 temp 常量中。否则,执行 else 代码的内容,然后返回调用函数。由于可选项类型有值,因此调用 print 函数。


4. 空合运算符(Nil-coalescing operator)

在 Swift 中,还可以使用空合运算符检查可选类型是否有值。其定义为(a??b)。它解包可选的 a 并返回它(如果它有值),或者如果 a 为零则返回默认值 b

实例 7:使用空合运算符的可选处理
  1. var someValue:Int!
  2. let defaultValue = 5
  3. let unwrappedValue:Int = someValue ?? defaultValue
  4. print(unwrappedValue)

结果如下:

  1. 5

在上面的程序中,变量 someValue 被定义为可选的,并且包含 nil 值。空合运算符无法解包可选值,因此返回默认值。因此,语句 print(unwrappedValue) 在控制台中输出 5

  1. var someValue:Int? = 10
  2. let defaultValue = 5
  3. let unwrappedValue:Int = someValue ?? defaultValue
  4. print(unwrappedValue)

结果如下:

  1. 10

然而,在上面的程序中,可选变量 someValue 被初始化为 10。因此,空合运算符成功地从 someValue 中解包该值。因此,声明 someValue??defaultValue 返回 10,语句 print(unwrappedValue) 在控制台中输出 10