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时,不要使用隐式解包。 如果需要在变量的生命周期中检查有没有值,请始终使用正常的可选类型(在变量声明的时候加?)。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,830评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,992评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,875评论 0 331
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,837评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,734评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,091评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,550评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,217评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,368评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,298评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,350评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,027评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,623评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,706评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,940评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,349评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,936评论 2 341

推荐阅读更多精彩内容