# Swift 可选项

> 原文： [https://www.programiz.com/swift-programming/optionals](https://www.programiz.com/swift-programming/optionals)

#### 在本文中，您将学习可选项，其用例以及 Swift 中的可选项处理。

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

**示例**：

```swift
let someValue = Int()
print(someValue)

```

运行该程序时，输出为：

```swift
0
```

但是，Swift 中还有另一种称为`Optional`的数据类型，其默认值为空值（`nil`）。 如果希望变量或常量中不包含任何值，则可以使用可选项。 可选项可以包含一个值或不存在一个值（空值）。

从技术上讲，您可以认为它是可选的鞋盒。 鞋盒中可能装有鞋，也可能没有。 因此，从包装箱中取出鞋子时，您应该事先知道。

* * *

## 如何声明`Optional`？

通过将`!`或`?`附加到`Type`，您可以简单地将数据类型表示为`Optional`。 如果一个可选参数中包含一个值，则返回值为`Optional<Value>`，否则返回`nil`。

### 示例 1：如何在 Swift 中声明一个可选项？

```swift
var someValue:Int?
var someAnotherValue:Int!
print(someValue)
print(someAnotherValue) 
```

运行该程序时，输出为：

```swift
nil
nil
```

在上面的程序中，我们使用`?`和`!`初始化了一个可选项。 两种方法都是可以创建可选项的方法，但是有一个主要的不同，我们将在下面进行探讨。

声明一个可选的`Int`意味着该变量将具有整数值或无值。 由于没有为变量分配任何值，因此您可以在屏幕上看到两个`print`语句输出`nil`。

* * *

### 示例 2：从可选项分配和访问值

```swift
let someValue:Int? = 5
print(someValue)
print(someValue!) 
```

运行该程序时，输出为：

```swift
Optional(5)
5 
```

在上面的程序中，我们声明了`Int`类型的可选项，并在其中分配了值 5。

如您所见，将可选项打印为`print(someValue)`不会给您`5`而是`Optional(5)`。 它具有上述形式：`Optional<Value>`。 为了从中访问`<Value>`，我们需要一种称为**展开**的机制。

您可以通过在变量/常量的末尾附加`!`字符来展开可选字符，如下一行`print(someValue!)`所示。`print(someValue!)`打开包装，并在屏幕上输出`5`。

但是，请记住，仅当确定在访问可选项时肯定具有值时，才应使用这种解包机制。

* * *

### 示例 3：显式声明一个未包装的可选项

您还可以通过以下方式创建解包后的可选项：

```swift
let someValue:Int! = 5
print(someValue) 
```

运行该程序时，输出为：

```swift
5
```

在上面的程序中，`Int!`创建一个未包装的可选项，当您访问它时，它会自动对值进行包装，因此您不必每次都附加`!`字符。

请确保在使用这些可选项时，变量在访问它时始终需要有一个值。 如果不这样做，将会导致致命的错误崩溃。

* * *

### 示例 4：访问`null`的未包装可选对象时发生致命错误

```swift
var someValue:Int!
var unwrappedValue:Int = someValue //crashes due to this line 
```

当您运行该程序时，您会因**致命错误**而崩溃：在解开可选项时意外发现`nil`，因为代码`unwrappedValue:Int = someValue`试图将可选`someValue`中的值赋给变量`unwrappedValue`。

但是，`somevalue`是包含`nil`值的`Optional`类型。 尝试将`nil`值分配给变量`unwrappedValue`（这不是可选的）会导致崩溃。

有多种处理此情况的技术，下面将进行说明。

* * *

## 可选项处理

为了使用可选项，需要将其解包。 使用可选项的更好方法是通过条件展开而不是使用`!`运算符强制展开。

这是因为有条件的展开询问**检查此变量是否具有值？**。 如果是，请提供该值，否则将处理`nil`情况。

相反，强制展开表示**该变量在使用时确实有一个值**。 因此，当您强制解开一个`nil`的变量时，您的程序将在解开可选异常并抛出的同时抛出**意外发现的`nil`**。 下面说明了一些用于条件展开的技术：

### 1\. `If`语句

您可以使用`if`语句，然后将可选参数与`nil`进行比较，以找出可选参数是否包含值。 您可以在`if`语句中使用比较运算符“等于”运算符（`==`）或“不等于”运算符（`!=`）。

#### 示例 5：`if else`语句的可选项处理

```swift
var someValue:Int?
var someAnotherValue:Int! = 0

if someValue != nil {
	print("It has some value \(someValue!)")
} else {
	print("doesn't contain value")
}

if someAnotherValue != nil {
	print("It has some value \(someAnotherValue!)")
} else {
	print("doesn't contain value")
} 
```

运行该程序时，输出为：

```swift
doesn't contain value
It has some value 0 
```

在上面的程序中，如果可选项包含值，则执行`if`语句内的代码，否则执行`else`块内的语句。 使用此技术进行可选项处理的主要缺点是，您仍然需要使用`!`运算符从可选项中解包该值。

* * *

### 2.可选绑定（如果允许）

可选绑定可帮助您找出可选项是否包含值。 如果可选项包含一个值，则该值可用作临时常量或变量。 因此，可以将可选绑定与`if`语句一起使用，以检查可选项内部的值，并在单个操作中将该值提取到常量或变量中。

#### 示例 5：使用`if let`语句的可选项处理

```swift
var someValue:Int?
var someAnotherValue:Int! = 0

if let temp = someValue {
	print("It has some value \(temp)") 
} else {
	print("doesn't contain value")
}

if let temp = someAnotherValue {
	print("It has some value \(temp)")
} else {
	print("doesn't contain value")      
} 
```

运行该程序时，输出为：

```swift
doesn't contain value
It has some value 0 
```

在上面的程序中，如果可选项包含一个值，则执行`if`语句中的代码。 否则，`else`块将被执行。`if-let`语句还自动展开该值，并将展开后的值放入`temp`常量中。 该技术的主要优势在于，尽管可以确定某个可选项包含一个值，但您无需强行解开该值。

* * *

### 3.`guard`语句

您可以使用`guard`处理 Swift 中的可选项。 如果您不知道什么警卫，请不要担心。 现在，仅将警卫视为没有`if`块的`if-else`条件。 如果条件失败，则执行`else`语句。 如果不是，则执行下一条语句。 有关更多详细信息，请参见 [Swift `Guard`](/swift-programming/guard-statement "Swift guard statement")。

#### 示例 6：使用`guard`的可选项处理

```swift
func testFunction() {
	let someValue:Int? = 5
	guard let temp = someValue else {
		return
	}
	print("It has some value \(temp)")
}

testFunction() 
```

运行该程序时，输出为：

```swift
It has some value 5
```

在上述程序中，防护包含一个条件，即可选的`someValue`是否包含值。 如果它包含一个值，则`guard-let`语句将自动解包该值，并将解包后的值放入`temp`常量中。 否则，`else`块将被执行，它将返回到调用函数。 由于可选项包含一个值，因此将调用`print`函数。

* * *

### 4.`nil`折叠运算符

在 Swift 中，您还可以使用`nil`折叠运算符检查可选变量是否包含值。 定义为`(a ?? b)`。 它解开可选的`a`并返回它（如果它包含一个值），或者如果`a`为零，则返回默认值`b`。

#### 示例 7：使用`nil`折叠运算符的可选项处理

```swift
var someValue:Int!
let defaultValue = 5
let unwrappedValue:Int = someValue ?? defaultValue
print(unwrappedValue) 
```

运行该程序时，输出为：

```swift
5
```

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

```swift
var someValue:Int? = 10
let defaultValue = 5
let unwrappedValue:Int = someValue ?? defaultValue
print(unwrappedValue) 
```

运行该程序时，输出为：

```swift
10
```

但是，在上述程序中，可选变量`someValue`初始化为值 10。因此，nil 合并运算符成功地从`someValue`中解包了该值。 因此，语句`someValue ?? defaultValue`返回 10，并且语句`print(unwrappedValue)`在控制台中输出 10。