Swift语言指南(六)--可选值

原文:Swift语言指南(六)--可选值

在值可能不存在的情况下使用可选值(optional), 可选值是:

  · 存在一个值,这个值等于 x

  · 不存在任何值

 注:

在 C 和 Objective-C 中可选值的概念并不存在。Objective-C 中(与可选值)最相近的(概念)是,一个以对象为返回值的方法,也可以返回 nil,nil表示“不存在有效的对象”。不过,这规则只对对象有效——对于结构、基本的 C 类型或枚举值无效。对于这些类型,Objective-C 语言的方法通常会返回一个特殊值(如 NSNotFound)来表示值不存在。这种策略假定该方法的调用方知道要测试返回值是否等于某个特殊值,并且记得要作此检查。Swift 的可选值允许表示任何类型不存在值,无需定义特殊常量。

这里有个例子。Swift 的 String 类型有一个名为 toInt 的方法,可尝试将 String 值转为 Int 值。然而,不是所有字符串都可以转换为整数。字符串 “123”可以转换为数值 123,而字符串 “hello, world” 显然没有对应的数值。

下面的例子会尝试用 toInt 方法将 String 转换为 Int

1 let possibleNumber(可能是数字) = "123"
2 let convertedNumber(转换得到的数字) = possibleNumber.toInt() 3 //convertedNumber被推断为 "Int?" 类型,或 "可选的 Int"

因为 toInt 方法可能会转换失败,因此它返回的是一个 可选的 Int 型,而不是 Int 型。可选的 Int写法为 Int?,而不是 Int。问号表明示该类型包含的值是可选的,即 Int? 可能包含某个 Int 类型的值,也可能不含任何值。(它不能包含其他类型的值,如 Bool 值或 String 值,它要么是 Int 要么就不存在。)

 

if 语句与强制拆包

可使用 if 语句测试可选值是否含有值。如果有,则求值结果返回 true,否则返回 false

一旦确认可选值的确含有一个值,就可以通过在可选值变量名的末尾添加感叹号(!)来访问其内部的值。感叹号明确表达:“我知道这个可选值确实存在值,请使用它(那个值)吧!”这种操作名为对可选值进行强制拆包force-unwrap):

  1. 1 if convertedNumber(转换后得到的数字) {
    2     println("\(possibleNumber) 的整数值为 \(convertedNumber!)")
    3 } else {
    4     println("\(possibleNumber) 不能转换为一个整数")
    5 }
    6 // 输出 "123 的整数值为 123"

关于 if 语句的更多信息,请见 流程控制

 

注:

尝试用 ! 访问不存在的可选值时会在运行时报错,在用 ! 强行拆包之前,务必确保可选值确实包含一个非 nil 的值。

 

可选值绑定

可以使用可选值绑定optional binding)测试可选值是否包含一个值,如果有,则将该值以临时常量或变量的形式拆包备用。可选值绑定可以与 if 或 while 语句结合使用,这样只需要一步就可以检查是否存在值、提取该值、并存放到常量或变量中。关于 if 与 while 语句的更多信息在 流程控制 一章中有讲过。

可选值绑定与 if 混用可以是这样:

1 if let constantName = someOptional {
2     statements
3 }

 

上文中的 possibleNumber 一例,可以用可选值绑定代替强制拆包:

1 if let actualNumber = possibleNumber.toInt() {
2      println("\(possibleNumber) 的整数值为 \(actualNumber)")
3 } else {
4      println("\(possibleNumber) 无法转换为整数")
5 }
6  // 输出 "123 的整数值为 123"

可以这样理解:

“如果 possibleNumber.toInt() 返回的 可选的 Int 包含一个值,则新建一个名为 actualNumber 的常量,并将常量的值设为可选值中包含的值。”

如果转换成功,常量 actualNumber 将可供 if 语句的第一个分支语句使用。该常量已经被可选值包含的值初始化,因此不再需要用后缀 ! 访问其值。本例中,actualNumber 被直接用来输出转换结果。

常量与变量均可用于可选值绑定。如果需要在第一个分支中处理 actualNumber 的值,可以改写为 if var actualNumber,这样可选值的值将作为变量而非常量拆包。

 

nil

要将可选变量设为空值(没有值或值不存在的状态,valueless),可以给它赋特殊值 nil

1 var serverResponseCode(服务器状态码): Int? = 404
2 //服务器状态码包含一个实际存在的 Int 值:404 3 serverResponseCode= nil 4 // 服务器状态码 现在不含任何值

 

注:

nil 不能用于非可选值的常量或变量。如果代码中的常量或变量需要适配值不存在的某种特殊情况,务必将它声明为适用的可选值类型

如果你所定义的可选值未提供默认值,该常量或变量将被自动设为 nil

1 var surveyAnswer: String?
2 // surveyAnswer 被自动设为 nil

 

注:

Swift 的 nil 与 Objective-C 的 nil 不同。Objective-C 的 nil 是指向一个不存在对象的指针,而 Swift 的 nil 不是指针——它是一种表示值不存在的特殊类型。任何类型的可选值都能赋值为nil,不仅限于对象类型。

 

可选值的隐式拆包

如上所述,可选值指允许“值不存在”的常量或变量。可以通过 if 语句测试可选值是否存在值,也可以通过可选值绑定按条件拆包,并在该可选值的值存在的情况下才访问它的值。

有时根据程序结构可以知晓一个可选值在首次赋值后,必然存在值。这时,可以不必每次访问时都检测并提取该可选值的值,因为可以安全地假设它那时一定存在值。

这些可选值可定义为隐式拆包的可选值(implicitly unwrapped optional)。你可以通过在希望标为可选的类型名称后面,用感叹号 (String!) 代替问号 (String?)的方式书写隐式拆包可选值

隐式拆包的可选值在可选值首次定义后即确认存在值,在此之后任何时刻都能被明确地(肯定有值)使用。Swift 中隐式拆包可选值主要应用于类初始化,详见 外部引用与隐式拆包的可选属性(待译)。

隐式拆包的可选值在运行环境里就是普通的可选值,但能够像非可选值那样使用,无需在每次访问时拆包。下例显示了 可选的 String 与 隐式拆包的可选 String 之间的行为差异:

1 let possibleString(可能的字符串): String? = "An optional String。(一个可选的String)"
2 println(possibleString!) // 访问其值时需要添加感叹号
3 // 输出 "可选的 String。"
4 let assumedString(假设的字符串): String! = "An implicitly unwraped optional String。(隐式的拆包的可选Stirng)" 5 println(assumedString) // 访问其值时无需感叹号 6 // 输出 "隐式拆包的可选 String。"

 

可以认为,隐式拆包的可选值即授予可选值在被使用时自动拆包的权限(即无需再次手动进行拆包)。不必每次使用可选值时都在名称后面添加感叹号,只需在声明时在可选值类型后面加上感叹号即可。

 

注:如果在隐式拆包的可选值存在值之前就尝试访问(不存在值时不可进行隐式拆包),运行时会报错。结果与在普通可选值尚未赋值时直接加感叹号就引用相同。

隐式拆包的可选值也可以当作像普通可选值那样,检查是否存在值:

1 if assumedString {
2     println(assumedString)
3 }
4 // 输出 "An implicitly unwraped optional String。(隐式的拆包的可选Stirng)"

 

隐式拆包的可选值同样可以使用可选值绑定,单条语句完成检查值并拆包:

1 if let definiteString(肯定是字符串) = assumedString(假定是字符串) {
2    println(definiteString)
3  }
4 // 输出 "隐式拆包的可选 String。"

 

 

注:

当变量在后续过程中可能变为 nil 时,不应使用隐式拆包的可选值。如果在变量声明周期内都需要检查 nil 值,请务必使用普通的可选类型量。

 

谢谢,Swifter-QQ群:362232993,同好者进~ 

Fork:https://github.com/Joejo/Swift-lesson-for-chinese

 

 

 

 

 

时间: 2024-09-15 20:24:28

Swift语言指南(六)--可选值的相关文章

Swift语言指南(六) Swift语言的可选值

在值可能不存在的情况下使用可选值(optional), 可选值是: · 存在一个值,这个值等于 x 或 · 不存在任何值 注: 在 C 和 Objective-C 中可选值的概念并不存在.Objective-C 中(与可选值)最相近的(概念)是,一个以对象为返回值的方法,也可以返回 nil,nil表示"不存在有效的对象".不过,这规则只对对象有效--对于结构.基本的 C 类型或枚举值无效.对于这些类型,Objective-C 语言的方法通常会返回一个特殊值(如 NSNotFound)来

Swift语言指南(七)--语言基础之布尔值和类型别名

原文:Swift语言指南(七)--语言基础之布尔值和类型别名   布尔值   Swift有一个基本布尔类型,叫做布尔(bool),布尔值又称逻辑值(logical),因为它只能为真(true)或假(false).Swift提供了两个布尔常量值:true,false: 1 let orangesAreOrange(橙子是橙子) = true 2 let turnipsAreDelicious(芜菁很美味) = false orangesAreOrange和turnipsAreDelicious被推

Swift语言指南(一) Swift语言基础:常量和变量

Swift 是开发 iOS 及 OS X 应用的一门新编程语言,然而,它的开发体验与 C 或 Objective-C 有很多相似之处. Swift 提供了 C 与 Objective-C 中的所有基础类型,包括表示整数的 Int,表示浮点数的 Double 与 Float,表示布尔值的 Bool,以及表示纯文本数据的 String. Swift 还为两个基本集合类型 Array 与 Dictionary 提供了强大的支持,详情可参考 (集合类型)Collection Types. 与 C 语言类

Swift语言指南(一)--语言基础之常量和变量

原文:Swift语言指南(一)--语言基础之常量和变量 Swift 是开发 iOS 及 OS X 应用的一门新编程语言,然而,它的开发体验与 C 或 Objective-C 有很多相似之处. Swift 提供了 C 与 Objective-C 中的所有基础类型,包括表示整数的 Int,表示浮点数的 Double 与 Float,表示布尔值的 Bool,以及表示纯文本数据的 String. Swift 还为两个基本集合类型 Array 与 Dictionary 提供了强大的支持,详情可参考 (集合

Swift语言指南(九)--基本运算符

原文:Swift语言指南(九)--基本运算符 运算符(operator)是用来检查,改变或合并值的一种特殊符号或短语.例如,加号运算符让两个数字相加(如:let i = 1 + 2),还有些更复杂的运算符,如逻辑与运算符(&&)(如:if enteredDoorCode && passedRetinaScan)和自增运算符(++i)(将 i 的值加 1 的便捷写法). Swift 支持标准C语言的大多数运算符,并且改进了一些特性以规避常见的代码错误.赋值运算符(=)是没有返

Swift语言指南(三)--语言基础之整数和浮点数

原文:Swift语言指南(三)--语言基础之整数和浮点数   整数   整数指没有小数的整数,如42,-23.整数可以是有符号的(正数,零,负数),也可以是无符号的(正数,零). Swift提供了8,16,32,64位形式的有符号和无符号的整数,这些整数遵循与C语言相似的命名规则.如8位无符号整数的类型为UInt8,32位有符号整数的类型为Int32,和Swift语言的其它类型一样,这些整型命名以大写字母开头.   整数的边界 你可以通过min或max属性为每一个整数类型指定一个最小值或最大值:

Swift语言指南(十)--字符串与字符

原文:Swift语言指南(十)--字符串与字符 字符串是一段字符的有序集合,如"hellow,world"或"信天翁".Swift 中的字符串由 String 类型表示,对应着 Character 类型值的集合. Swift 中的 String 类型为你的编程提供了一个高速的,兼容 Unicode规范 的文本处理方式.Swift 创建和处理字符串的语法轻量可读,与 C 语言的字符串语法颇为相似.字符串的拼接非常简单,只需将两个字符串用 + 运算符相加.字符串的值是否

Swift语言指南(二)--语言基础之注释和分号

原文:Swift语言指南(二)--语言基础之注释和分号 注释 通过注释向自己的代码中注入不可执行的文本,作为你自己的笔记或提示.Swift编译器运行时会忽略注释. Swift的注释与C语言极其相似,单行注释以两个反斜线开头: //这是一行注释 多行注释以/*开始,以*/结束: /* 这也是一条注释, 但跨越多行 */ 与 C 语言的多行注释有所不同的是,Swift 的多行注释可以嵌套在其他多行注释内部.写法是在一个多行注释块内插入另一个多行注释.第二个注释块封闭时,后面仍然接着第一个注释块: /

Swift语言指南(七) Swift语言基础:布尔值和类型别名

布尔值 Swift有一个基本布尔类型,叫做布尔(bool),布尔值又称逻辑值(logical),因为它只能为真(true)或假(false).Swift提供了两个布尔常量值:true,false: 1 let orangesAreOrange(橙子是橙子) = true 2 let turnipsAreDelicious(芜菁很美味) = false orangesAreOrange和turnipsAreDelicious被推断为布尔类型,因为它们的值被布尔字面量给初始化了.与前文提到的Int或