在上一篇文章中,我们了解了Swift中可用的不同数据类型,并且还注意到这些类型声明的变量或常量包含默认值。
例:
let someValue = Int()
print(someValue)
运行该程序时,输出为:
0
但是,Swift中还有另一种数据类型称为Optional,其默认值为null值( nil
)。如果希望变量或常量中不包含任何值,则可以使用可选。可选类型可以包含一个值或不存在一个值(空值)。
从技术上讲,您可以认为它是可选的鞋盒。鞋盒中可能装有鞋,也可能没有。因此,从包装箱中取出鞋子时,您应该事先知道。
如何声明一个可选的?
您可以通过追加将数据类型简单地表示为Optional !
还是?
的Type
。如果一个可选参数中包含一个值,则将其值返回为Optional
,否则返回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)
为print(someValue)
不会给您5
而是Optional(5)
。它具有如上所述的形式: Optional
。为了从中访问
,我们需要一种称为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
当您运行该程序时,您将得到致命错误的崩溃: unwrappedValue:Int = someValue
Optional值时意外发现nil,因为代码unwrappedValue:Int = someValue
试图将Optional someValue中的值分配给变量unwrappedValue 。
但是, somevalue是包含nil
值的Optional
类型。尝试将nil值分配给变量unwrappedValue(这不是可选的)会导致崩溃。
有多种处理此情况的技术,下面将进行说明。
可选处理
为了使用可选值,需要将其解包。使用可选值的更好方法是通过条件展开,而不是使用!
强制展开!
运算符。
这是因为有条件的展开询问是否检查此变量是否有值? 。如果是,请提供该值,否则将处理nil情况。
相反,强制展开表示此变量在使用时确实具有一个值 。因此,当您强制解开一个nil的变量时,您的程序将在解开一个可选异常并崩溃时抛出意外发现的nil 。下面说明了一些用于条件展开的技术:
1.陈述
您可以使用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在Swift中处理可选内容。如果您不知道什么警卫,请不要担心。现在,仅将警卫视为没有if块的if-else
条件。如果条件失败,则执行else语句。如果不是,则执行下一条语句。有关更多详细信息,请参见Swift Guard。
示例6:使用防护罩的可选处理
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
语句将自动解包该值并将解包后的值放入临时常量中。否则,else块将被执行,它将返回到调用函数。由于可选内容包含一个值,因此将调用print
函数 。
4.无销售运算符
在Swift中,您还可以使用nil-coalescing 运算符检查可选变量是否包含值。它定义为(a ?? b)
。它解开可选的a并返回它(如果它包含一个值),或者返回一个默认值b(如果a为零)。
示例7:使用nil-coalescing 运算符的可选处理
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。