原文: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

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

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

if 语句与强制拆包

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

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

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

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

注:

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

可选值绑定

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

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

 if let constantName = someOptional {
statements
}

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

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

可以这样理解:

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

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

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

nil

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

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

注:

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

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

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

注:

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

可选值的隐式拆包

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

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

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

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

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

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

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

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

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

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

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

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

注:

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

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

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

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

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

    原文:Swift语言指南(七)--语言基础之布尔值和类型别名 布尔值 Swift有一个基本布尔类型,叫做布尔(bool),布尔值又称逻辑值(logical),因为它只能为真(true)或假(false ...

  2. Swift语言指南(五)--数字字面量和数字类型转换

    原文:Swift语言指南(五)--数字字面量和数字类型转换 数字字面量 整数字面量写法如下: · 十进制数,无前缀 · 二进制数,以 0b 为前缀 · 八进制数,以 0o 为前缀 · 十六进制数,以 ...

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

    原文:Swift语言指南(一)--语言基础之常量和变量 Swift 是开发 iOS 及 OS X 应用的一门新编程语言,然而,它的开发体验与 C 或 Objective-C 有很多相似之处. Swif ...

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

    原文:Swift语言指南(九)--基本运算符 运算符(operator)是用来检查,改变或合并值的一种特殊符号或短语.例如,加号运算符让两个数字相加(如:let i = 1 + 2),还有些更复杂的运 ...

  5. Swift语言指南(四)--类型安全和类型推断

    原文:Swift语言指南(四)--类型安全和类型推断 Swift是一门类型安全语言,类型安全语言需要代码里值的类型非常明确.如果你的代码中有部分值需要String类型,你就不能错误地传递Int. 鉴于 ...

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

    原文:Swift语言指南(三)--语言基础之整数和浮点数 整数 整数指没有小数的整数,如42,-23.整数可以是有符号的(正数,零,负数),也可以是无符号的(正数,零). Swift提供了8,16,3 ...

  7. Swift语言指南(八)--语言基础之元组

    原文:Swift语言指南(八)--语言基础之元组 元组 元组(Tuples)将多个值组合为一个复合值.元组内的值可以是任何类型,各个元素不需要为相同类型(各个元素之间类型独立,互不干扰--Joe.Hu ...

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

    原文:Swift语言指南(十)--字符串与字符 字符串是一段字符的有序集合,如"hellow,world"或"信天翁".Swift 中的字符串由 String ...

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

    原文:Swift语言指南(二)--语言基础之注释和分号 注释 通过注释向自己的代码中注入不可执行的文本,作为你自己的笔记或提示.Swift编译器运行时会忽略注释. Swift的注释与C语言极其相似,单 ...

随机推荐

  1. 【足迹C++primer】48、函数引用操作符

    函数引用操作符 struct absInt { int operator()(int val) const { cout<<val<<"<->!!!&qu ...

  2. [Python 学习] 两、在Linux使用平台Python

    在本节,它介绍了Linux如何使用平台Python 1. Python安装. 今天,大多数把自己的版本号Python的,它不能被安装.假设你要安装它,可以使用相应的安装指令. Fedora:先以roo ...

  3. Design Pattern Command 命令设计模式

    这种设计模式是使用不同类的包裹不同的命令,达到什么样的命令执行什么操作. 有可能进一步利用map您最喜欢的对接命令字. 正在运行的类实际上已经包含了操作的所有需求,例如: class SuperMak ...

  4. 跟我一起学extjs5(37--单个模块的设计[5取得模块列表数据])

    跟我一起学extjs5(37--单个模块的设计[5取得模块列表数据])         写了几个月,总算有点盼头了,最终要从后台取得数据了.后台的spring mvc 和 service 仅仅能简单的 ...

  5. Maven构建Hadoop

    Maven构建Hadoop工程 阅读目录 序 Maven 安装 构建 示例下载 系列索引 序 上一篇,我们编写了第一个MapReduce,并且成功的运行了Job,Hadoop1.x是通过ant来管理工 ...

  6. Canvas 生成base64的PNG图片快照,So Amazing!!!

    function canvasSupport(){     return Modernizr.canvas;}function callCanvasApps(){  var canvasOne=doc ...

  7. Android-往来:添加到联系人

    //添加到联系人.使用事务 public void testAddContact() { String name[]={"周杰伦","谢霆锋","言承 ...

  8. 提高duilib的richedit控制的一些特征

    转载请注明原始出处.谢谢~~:http://blog.csdn.net/zhuhongshu/article/details/41208207 假设要使用透明异形窗口功能,首先要改进duilib库让他 ...

  9. whu oj 1551 Pairs (莫队算法)

    problem_id=1551">题目链接 题目大意: 给出的询问,求出这个区间的里 差小于等于 2 的数字的对数. 思路分析: 莫队算法. 然后分析一下. 假设添加了一个数字.那么就 ...

  10. 看多csdn它还烂论坛?

    什么? 版权声明:本文博主原创文章,博客,未经同意不得转载.