在本文中,您将学习可选项,其用例以及 Swift 中的可选项处理。
在上一篇文章中,我们了解了 Swift 中可用的不同数据类型,并且还注意到这些类型声明的变量或常量包含默认值。
示例:
let someValue = Int()
print(someValue)
运行该程序时,输出为:
0
但是,Swift 中还有另一种称为Optional
的数据类型,其默认值为空值(nil
)。 如果希望变量或常量中不包含任何值,则可以使用可选项。 可选项可以包含一个值或不存在一个值(空值)。
从技术上讲,您可以认为它是可选的鞋盒。 鞋盒中可能装有鞋,也可能没有。 因此,从包装箱中取出鞋子时,您应该事先知道。
如何声明Optional
?
通过将!
或?
附加到Type
,您可以简单地将数据类型表示为Optional
。 如果一个可选参数中包含一个值,则返回值为Optional<Value>
,否则返回nil
。
示例 1:如何在 Swift 中声明一个可选项?
var someValue:Int?
var someAnotherValue:Int!
print(someValue)
print(someAnotherValue)
运行该程序时,输出为:
nil
nil
在上面的程序中,我们使用?
和!
初始化了一个可选项。 两种方法都是可以创建可选项的方法,但是有一个主要的不同,我们将在下面进行探讨。
声明一个可选的Int
意味着该变量将具有整数值或无值。 由于没有为变量分配任何值,因此您可以在屏幕上看到两个print
语句输出nil
。
示例 2:从可选项分配和访问值
let someValue:Int? = 5
print(someValue)
print(someValue!)
运行该程序时,输出为:
Optional(5)
5
在上面的程序中,我们声明了Int
类型的可选项,并在其中分配了值 5。
如您所见,将可选项打印为print(someValue)
不会给您5
而是Optional(5)
。 它具有上述形式:Optional<Value>
。 为了从中访问<Value>
,我们需要一种称为展开的机制。
您可以通过在变量/常量的末尾附加!
字符来展开可选字符,如下一行print(someValue!)
所示。print(someValue!)
打开包装,并在屏幕上输出5
。
但是,请记住,仅当确定在访问可选项时肯定具有值时,才应使用这种解包机制。
示例 3:显式声明一个未包装的可选项
您还可以通过以下方式创建解包后的可选项:
let someValue:Int! = 5
print(someValue)
运行该程序时,输出为:
5
在上面的程序中,Int!
创建一个未包装的可选项,当您访问它时,它会自动对值进行包装,因此您不必每次都附加!
字符。
请确保在使用这些可选项时,变量在访问它时始终需要有一个值。 如果不这样做,将会导致致命的错误崩溃。
示例 4:访问null
的未包装可选对象时发生致命错误
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
语句的可选项处理
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")
}
运行该程序时,输出为:
doesn't contain value
It has some value 0
在上面的程序中,如果可选项包含值,则执行if
语句内的代码,否则执行else
块内的语句。 使用此技术进行可选项处理的主要缺点是,您仍然需要使用!
运算符从可选项中解包该值。
2.可选绑定(如果允许)
可选绑定可帮助您找出可选项是否包含值。 如果可选项包含一个值,则该值可用作临时常量或变量。 因此,可以将可选绑定与if
语句一起使用,以检查可选项内部的值,并在单个操作中将该值提取到常量或变量中。
示例 5:使用if let
语句的可选项处理
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")
}
运行该程序时,输出为:
doesn't contain value
It has some value 0
在上面的程序中,如果可选项包含一个值,则执行if
语句中的代码。 否则,else
块将被执行。if-let
语句还自动展开该值,并将展开后的值放入temp
常量中。 该技术的主要优势在于,尽管可以确定某个可选项包含一个值,但您无需强行解开该值。
3.guard
语句
您可以使用guard
处理 Swift 中的可选项。 如果您不知道什么警卫,请不要担心。 现在,仅将警卫视为没有if
块的if-else
条件。 如果条件失败,则执行else
语句。 如果不是,则执行下一条语句。 有关更多详细信息,请参见 Swift Guard
。
示例 6:使用guard
的可选项处理
func testFunction() {
let someValue:Int? = 5
guard let temp = someValue else {
return
}
print("It has some value \(temp)")
}
testFunction()
运行该程序时,输出为:
It has some value 5
在上述程序中,防护包含一个条件,即可选的someValue
是否包含值。 如果它包含一个值,则guard-let
语句将自动解包该值,并将解包后的值放入temp
常量中。 否则,else
块将被执行,它将返回到调用函数。 由于可选项包含一个值,因此将调用print
函数。
4.nil
折叠运算符
在 Swift 中,您还可以使用nil
折叠运算符检查可选变量是否包含值。 定义为(a ?? b)
。 它解开可选的a
并返回它(如果它包含一个值),或者如果a
为零,则返回默认值b
。
示例 7:使用nil
折叠运算符的可选项处理
var someValue:Int!
let defaultValue = 5
let unwrappedValue:Int = someValue ?? defaultValue
print(unwrappedValue)
运行该程序时,输出为:
5
在上面的程序中,变量someValue
定义为项,并且包含nil
值。 nil
合并运算符无法解开可选项,因此返回defaultValue
。 因此,语句print(unwrappedValue)
在控制台中输出 5。
var someValue:Int? = 10
let defaultValue = 5
let unwrappedValue:Int = someValue ?? defaultValue
print(unwrappedValue)
运行该程序时,输出为:
10
但是,在上述程序中,可选变量someValue
初始化为值 10。因此,nil 合并运算符成功地从someValue
中解包了该值。 因此,语句someValue ?? defaultValue
返回 10,并且语句print(unwrappedValue)
在控制台中输出 10。