Swift-可选类型

在值可能不存在的情况下,您可以使用可选值。 可选表示两种可能性:有一个值,您可以解开可选值以访问该值,或者根本没有值。
这里有一个例子说明如何使用可选项来处理缺少值。 Swift的Int类型有一个初始化器,它试图将String值转换为Int值。 但是,不是每个字符串都可以转换为整数。 字符串“123”可以转换为数字值123,但是字符串“hello,world”没有一个明显的数值要转换。

let possibleNumber = "123"
let convertedNumber = Int(possibleNumber)
// convertedNumber is inferred to be of type "Int?", or "optional Int"

因为初始化程序可能失败,它返回一个可选的Int,而不是一个Int。 可选的Int被写为Int ?,而不是Int。 问号表示它包含的值是可选的,这意味着它可能包含一些Int值,或者它可能不包含任何值。 (它不能包含任何其他的,如Bool值或String值,它是一个Int,或者它根本不是。
您通过为可选变量赋值特殊值nil将其设置为无价值状态:

var serverResponseCode: Int? = 404
// serverResponseCode contains an actual Int value of 404
serverResponseCode = nil
// serverResponseCode now contains no value

nil不能与非可选常量和变量一起使用。 如果代码中的常量或变量需要在某些条件下缺少某个值,请将其声明为适当类型的可选值。
如果您定义一个可选变量而不提供默认值,则变量将自动设置为nil:

var surveyAnswer: String?
// surveyAnswer is automatically set to nil

注意:Swift的nil与Objective-C中的nil不一样。 在Objective-C中,nil是一个指向不存在的对象的指针。 在Swift中,nil不是一个指针 - 它是一个类型的值的缺失。 任何类型的可选项都可以设置为nil,而不仅仅是对象类型。

if语句和强制解包

您可以使用if语句通过将可选项与nil进行比较来确定可选项是否包含值。 您可以使用“等于”运算符(==)或“不等于”运算符(!=)执行此比较。
如果一个可选项有一个值,它被认为是“不等于”nil:

if convertedNumber != nil {
    print("convertedNumber contains some integer value.")
}
// Prints "convertedNumber contains some integer value."

一旦确定可选项包含一个值,就可以通过在可选项名称的末尾添加一个感叹号(!)来访问其底层值。 这被称为强制解开可选值的值(强制解包):

if convertedNumber != nil {
print("convertedNumber has an integer value of \(convertedNumber!).")
}
// Prints "convertedNumber has an integer value of 123."

可选绑定

您可以使用可选绑定来确定一个可选的是否包含一个值,如果包含,则使该值作为临时常量或变量。 可选绑定可以与if和while语句一起使用,以检查可选内部中的值,并将该值提取为常量或变量,作为单个操作的一部分。
为if语句编写可选绑定,如下所示:

let possibleNumber = "123"
if let actualNumber = Int(possibleNumber) {
    print("\"\(possibleNumber)\" has an integer value of \(actualNumber)")
} else {
    print("\"\(possibleNumber)\" could not be converted to an integer")
}
// Prints ""123" has an integer value of 123"
这段代码的意思是:“如果Int(possibleNumber)返回的可选Int包含一个值,请将一个名为actualNumber的新常量设置为可选值中包含的值。
  • 如果转换成功,actualNumber常量可以在if语句的第一个分支中使用。 它已经被包含在可选内容中的值初始化,因此没有必要使用! 后缀来访问它的值。 在此示例中,actualNumber仅用于打印转换的结果。
  • 您可以使用常量和变量与可选绑定。 如果你想在if语句的第一个分支中操作actualNumber的值,你可以改写var actualNumber,并且可选内容中包含的值将作为变量而不是常量。

您可以根据需要在单个if语句中包含尽可能多的可选绑定和布尔条件,并以逗号分隔。 如果可选绑定中的任何值为nil或任何布尔条件求值为false,则整个if语句的条件被视为false。 以下if语句是等效的:

if let firstNumber = Int("4"), let secondNumber = Int("42"), firstNumber < secondNumber && secondNumber < 100 {
    print("\(firstNumber) < \(secondNumber) < 100")
}
// Prints "4 < 42 < 100"

if let firstNumber = Int("4") {
    if let secondNumber = Int("42") {
        if firstNumber < secondNumber && secondNumber < 100 {
            print("\(firstNumber) < \(secondNumber) < 100")
        }
    }
}
// Prints "4 < 42 < 100"

在if语句中使用可选绑定创建的常量和变量仅在if语句的主体中可用。 相反,用guard语句创建的常量和变量在保护语句之后的代码行中可用。

隐式解包

  • 如上所述,可选项指示允许常数或变量具有“nil”。 可选项可以使用if语句检查以查看值是否存在,并且可以使用可选绑定有条件地解开,以访问可选值(如果存在)。
  • 有时,从程序的结构中可以清楚地看出,可选项将始终具有值,在该值首次设置之后。 在这些情况下,删除每次访问可选值时都需要检查和解开可选值,这是非常有用的,因为它可以安全地假定所有时间都有一个值。
  • 这些类型的可选项被定义为隐式解包的可选项。 通过在要使其可选的类型之后放置感叹号(String!)而不是问号(String?)来编写隐式解包的可选属性。
  • 当Swift中隐式解包的可选属性的主要用途是在类初始化期间。

隐式解包的可选是后台的正常可选,但也可以像非可选值一样使用,而不需要在每次访问时解包可选值。 以下示例显示了在将其包装值作为显式字符串访问时,可选字符串和隐式未包装可选字符串之间的行为差异:

let possibleString: String? = "An optional string."
let forcedString: String = possibleString! // requires an exclamation mark

let assumedString: String! = "An implicitly unwrapped optional string."
let implicitString: String = assumedString // no need for an exclamation mark

您可以将隐式展开的可选项视为授予可选项在使用时自动展开的权限。 在每次使用可选名称后,不要在可选名称后面放置感叹号,而是在声明后在可选类型之后放置感叹号。
注意:如果隐式解包的可选项为nil,并且尝试访问其包装值,则会触发运行时错误。 结果与在不包含值的正常可选参数之后放置感叹号完全相同。
您仍然可以将一个隐式解开的可选项(如普通可选项)视为是否包含值:

if assumedString != nil {
    print(assumedString)
}
// Prints "An implicitly unwrapped optional string."

您还可以使用带有可选绑定的隐式解包可选,以在单个语句中检查和解包其值:

if let definiteString = assumedString {//如果隐式解包中的无值(nil)则视为解包失败,如果有值,就把这个作为一个新值,去创建一个名为‘definiteString’的常量,这个常量在if的语句体内可用。
    print(definiteString)
}
// Prints "An implicitly unwrapped optional string."

注意:当变量有可能在程序中变为nil时,不要使用隐式解包。 如果需要在变量的生命周期中检查有没有值,请始终使用正常的可选类型(在变量声明的时候加?)。

你可能感兴趣的:(Swift-可选类型)