Swift 可选类型(Optional)
在本文中,您将学习可选,其用例以及Swift中的可选处理。
在上一篇文章中,我们了解了Swift中可用的不同数据类型,并且还注意到这些类型声明的变量或常量包含默认值。
例:
let someValue = Int() print(someValue)
运行该程序时,输出为:
0
但是,Swift中还有另一种称为 Optional 的数据类型,其默认值为空值(nil)。如果希望变量或常量中不包含任何值,则可以使用 Optional。可选类型可以包含一个值或不存在一个值(空值)。
从技术上讲,您可以认为它是可选的鞋盒。鞋盒中可能装有鞋,也可能没有。因此,从包装箱中取出鞋子时,您应该事先知道。
如何声明一个可选的?
您可以通过追加将数据类型简单地表示为 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>,我们需要一种称为解包(unwrapping)的机制。
您可以通过在变量/常量的末尾附加字符 ! 来展开可选内容,如下一行所示 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
当您运行该程序时,您将得到致命错误的崩溃:解开Optional值时意外发现nil,因为代码unwrappedValue:Int = someValue试图将Optional someValue中的值分配给变量unwrappedValue。
但是,somevalue 是一个包含 nil 值的可选类型。试图将 nil 值分配给变量 unwrappedValue (这不是一个Optional)将导致崩溃。
下面将说明处理此情况的不同方法。
可选处理
为了使用可选值,需要将其解包。使用可选值的更好方法是通过条件解包,而不是使用 ! 运算符强制解包。
这是因为有条件的展开询问是否检查此变量是否有值?。如果是,请提供该值,否则将处理nil情况。
相反,强制展开表示此变量在使用时确实具有一个值。 因此,当您强制解开一个nil的变量时,您的程序将在解开一个可选异常并崩溃时抛出意外发现的nil。下面说明了一些用于条件展开的技巧:
1.if 语句
您可以使用if语句,然后将可选参数与nil进行比较,以找出可选参数是否包含值。您可以在if语句中使用比较运算符“等于”运算符(==)或“不等于”运算符(!=)。
示例5:if else语句的可选处理
var someValue:Int? var someAnotherValue:Int! = 0 if someValue != nil { print("包含值 \(someValue!)") } else { print("不包含值") } if someAnotherValue != nil { print("包含值 \(someAnotherValue!)") } else { print("不包含值") }
运行该程序时,输出为:
不包含值 包含值 0
在上面的程序中,如果可选语句包含值,则执行if语句内的代码,否则执行else块内的语句。使用此方法进行可选处理的主要缺点是,您仍然需要从可选中使用 ! 运算符解包该值。
2.可选绑定(if let)
可选绑定可帮助您找出可选值是否包含值。如果可选值包含一个值,则该值可用作临时常量或变量。因此,可以将可选绑定与if语句一起使用,以检查可选内部的值,并在单个操作中将其提取为常量或变量。
示例5:使用if let语句的可选处理
var someValue:Int? var someAnotherValue:Int! = 0 if let temp = someValue { print("包含值 \(temp)") } else { print("不包含值") } if let temp = someAnotherValue { print("包含值 \(temp)") } else { print("不包含值") }
运行该程序时,输出为:
不包含值 包含值 0
在上面的程序中,如果可选语句包含一个值,则执行if语句中的代码。否则,else块将被执行。if-let语句还自动解开该值,并将解开后的值存储在temp常量中。该方法的主要优势在于,尽管可以确定某个可选内容包含一个值,但您无需强行解开该值。
3.Guard 语句
您也可以在Swift中使用 guard 语句 处理可选内容。如果您不知道什么是 guard,请不要担心。现在,仅将guard视为if-else没有if阻止的条件。如果条件失败,则执行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
在上面的程序中,guard 包含一个条件,即可选的 someValue 是否包含一个值。如果它包含一个值,那么 guard-let 语句将自动解包该值并将解包的值放置在 temp 常量中。否则,else 块将被执行,并且它将返回到调用函数。因为可选项包含一个值,所以调用 print 函数。更多细节请参见Swift guard。
4.空合运算符(??)
在Swift中,您还可以使用空合运算符运算符检查可选项是否包含值。 它被定义为(a??b)。 它展开一个可选的a,如果它包含一个值,则返回它,或者如果a为空,则返回默认值b。
示例7:使用空合运算符的可选处理
var someValue:Int! let defaultValue = 5 let unwrappedValue:Int = someValue ?? defaultValue print(unwrappedValue)
运行该程序时,输出为:
5
在上面的程序中,变量someValue定义为可选,并且包含nil值。 空合运算符无法解开可选值,因此返回defaultValue。 因此,语句print(unwrappedValue)在控制台中输出5。
var someValue:Int? = 10 let defaultValue = 5 let unwrappedValue:Int = someValue ?? defaultValue print(unwrappedValue)
运行该程序时,输出为:
10
但是,在上述程序中,可选变量someValue被初始化为值10。因此,空合运算符成功地从中解包了该值someValue。因此,该语句在控制台台中someValue ?? defaultValue返回10,语句print(unwrappedValue)输出10。