Swift编程语言学习1.6——可选值

可选值

使用可选(optionals)来处理值可能缺失的情况。可选表示:

有值,等于 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 = "123"
let convertedNumber = possibleNumber.toInt()
// convertedNumber 被推测为类型"Int?",或者类型 "optional Int"

因为toInt方法可能会失败,所以它返回一个可选的(optional)Int,而不是一个Int。一个可选的Int被写作Int?而不是Int。问号暗示包含的值是可选,也就是说可能包含Int值也可能不包含值。(不能包含其他任何值比如Bool值或者String值。只能是Int或者什么都没有。)

if 语句以及强制解析

你可以使用if语句来判断一个可选是否包含值。如果可选有值,结果是true;如果没有值,结果是false。

当你确定可选包确实含值之后,你可以在可选的名字后面加一个感叹号(!)来获取值。这个惊叹号表示“我知道这个可选有值,请使用它。”这被称为可选值的强制解析(forced unwrapping):

if convertedNumber {
   println("\(possibleNumber) has an integer value of\(convertedNumber!)")
} else {
   println("\(possibleNumber) could not be converted to aninteger")
}
// 输出 "123 has aninteger value of 123"

更多关于if语句的内容,请参考控制流。

注意:

使用!来获取一个不存在的可选值会导致运行时错误。使用!来强制解析值之前,一定要确定可选包含一个非nil的值。

可选绑定

使用可选绑定(optional binding)来判断可选是否包含值,如果包含就把值赋给一个临时常量或者变量。可选绑定可以用在if和while语句中来对可选的值进行判断并把值赋给一个常量或者变量。if和while语句,请参考控制流。

像下面这样在if语句中写一个可选绑定:

if let constantName = someOptional {
   statements
}

你可以像上面这样使用可选绑定来重写possibleNumber这个例子:

if let actualNumber =possibleNumber.toInt() {
   println("\(possibleNumber) has an integer value of\(actualNumber)")
} else {
   println("\(possibleNumber) could not be converted to aninteger")
}
// 输出 "123 has aninteger value of 123"

这段代码可以被理解为:

“如果possibleNumber.toInt返回的可选Int包含一个值,创建一个叫做actualNumber的新常量并将可选包含的值赋给它。”

如果转换成功,actualNumber常量可以在if语句的第一个分支中使用。它已经被可选包含的值初始化过,所以不需要再使用!后缀来获取它的值。在这个例子中,actualNumber只被用来输出转换结果。

你可以在可选绑定中使用常量和变量。如果你想在if语句的第一个分支中操作actualNumber的值,你可以改成if var actualNumber,这样可选包含的值就会被赋给一个变量而非常量。

nil

你可以给可选变量赋值为nil来表示它没有值:

var serverResponseCode: Int? = 404
// serverResponseCode 包含一个可选的 Int 值 404
serverResponseCode = nil
// serverResponseCode 现在不包含值

注意:

nil不能用于非可选的常量和变量。如果你的代码中有常量或者变量需要处理值缺失的情况,请把它们声明成对应的可选类型。

如果你声明一个可选常量或者变量但是没有赋值,它们会自动被设置为nil:

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

注意:

Swift 的nil和 Objective-C中的nil并不一样。在 Objective-C 中,nil是一个指向不存在对象的指针。在 Swift 中,nil不是指针——它是一个确定的值,用来表示值缺失。任何类型的可选都可以被设置为nil,不只是对象类型。

隐式解析可选

如上所述,可选暗示了常量或者变量可以“没有值”。可选可以通过if语句来判断是否有值,如果有值的话可以通过可选绑定来解析值。

有时候在程序架构中,第一次被赋值之后,可以确定一个可选总会有值。在这种情况下,每次都要判断和解析可选值是非常低效的,因为可以确定它总会有值。

这种类型的可选被定义为隐式解析可选(implicitly unwrapped optionals)。把想要用作可选的类型的后面的问号(String?)改成感叹号(String!)来声明一个隐式解析可选。

当可选被第一次赋值之后就可以确定之后一直有值的时候,隐式解析可选非常有用。隐式解析可选主要被用在 Swift 中类的构造过程中,请参考类实例之间的循环强引用。

一个隐式解析可选其实就是一个普通的可选,但是可以被当做非可选来使用,并不需要每次都使用解析来获取可选值。下面的例子展示了可选String和隐式解析可选String之间的区别:

let possibleString: String? = "Anoptional string."
println(possibleString!) // 需要惊叹号来获取值
// 输出 "An optionalstring."
let assumedString: String! = "Animplicitly unwrapped optional string."
println(assumedString)  // 不需要感叹号
// 输出 "Animplicitly unwrapped optional string."

你可以把隐式解析可选当做一个可以自动解析的可选。你要做的只是声明的时候把感叹号放到类型的结尾,而不是每次取值的可选名字的结尾。

注意:

如果你在隐式解析可选没有值的时候尝试取值,会触发运行时错误。和你在没有值的普通可选后面加一个惊叹号一样。

你仍然可以把隐式解析可选当做普通可选来判断它是否包含值:

<pre name="code" class="java">if assumedString {
   println(assumedString)
}
// 输出 "Animplicitly unwrapped optional string."

你也可以在可选绑定中使用隐式解析可选来检查并解析它的值:

if let definiteString = assumedString {
   println(definiteString)
}
// 输出 "Animplicitly unwrapped optional string."

注意:

如果一个变量之后可能变成nil的话请不要使用隐式解析可选。如果你需要在变量的生命周期中判断是否是nil的话,请使用普通可选类型。

Swift编程语言学习1.6——可选值,布布扣,bubuko.com

时间: 2024-08-01 22:47:35

Swift编程语言学习1.6——可选值的相关文章

Swift编程语言学习1.5——类型别名、布尔值、元组

类型别名 类型别名(type aliases)就是给现有类型定义另一个名字.你可以使用typealias关键字来定义类型别名. 当你想要给现有类型起一个更有意义的名字时,类型别名非常有用.假设你正在处理特定长度的外部资源的数据: typealias AudioSample = UInt16 定义了一个类型别名之后,你可以在任何使用原始名的地方使用别名: var maxAmplitudeFound = AudioSample.min // maxAmplitudeFound 现在是 0 本例中,A

Swift编程语言学习1.7——断言

断言 可选可以让你判断值是否存在,你可以在代码中优雅地处理值缺失的情况.然而,在某些情况下,如果值缺失或者值并不满足特定的条件,你的代码可能并不需要继续执行.这时,你可以在你的代码中触发一个断言(assertion)来结束代码运行并通过调试来找到值缺失的原因. 使用断言进行调试 断言会在运行时判断一个逻辑条件是否为true.从字面意思来说,断言"断言"一个条件是否为真.你可以使用断言来保证在运行其他代码之前,某些重要的条件已经被满足.如果条件判断为true,代码运行会继续进行:如果条件

Swift编程语言学习——数值型字面量、数值类型转换

数值型字面量 整数字面量可以被写作: 一个十进制数,没有前缀 一个二进制数,前缀是0b 一个八进制数,前缀是0o 一个十六进制数,前缀是0x 下面的所有整数字面量的十进制值都是17: let decimalInteger = 17 let binaryInteger = 0b10001 // 二进制的17 let octalInteger = 0o21 // 八进制的17 let hexadecimalInteger = 0x11 // 十六进制的17 浮点字面量可以是十进制(没有前缀)或者是十

Swift编程语言学习2.2——基本运算符(下)

三元条件运算(Ternary Conditional Operator) 三元条件运算的特殊在于它是有三个操作数的运算符,它的原型是问题?答案1:答案2.它简洁地表达根据问题成立与否作出二选一的操作.如果问题成立,返回答案1的结果; 如果不成立,返回答案2的结果. 使用三元条件运算简化了以下代码: if question: { answer1 } else { answer2 } 这里有个计算表格行高的例子.如果有表头,那行高应比内容高度要高出50像素; 如果没有表头,只需高出20像素. let

Swift编程语言学习——常量与变量

常量和变量把一个名字(比如maximumNumberOfLoginAttempts或者welcomeMessage)和一个指定类型的值(比如数字10或者字符串"Hello")关联起来.常量的值一旦设定就不能改变,而变量的值可以随意更改. 声明常量和变量 常量和变量必须在使用前声明,用let来声明常量,用var来声明变量.下面的例子展示了如何用常量和变量来记录用户尝试登录的次数: let maximumNumberOfLoginAttempts = 10 var currentLogin

Swift编程语言学习2.1——基本运算符(上)

运算符是检查,改变,合并值的特殊符号或短语.例如,加号+将两个数相加(如let i = 1 + 2).复杂些的运行算例如逻辑与运算符&&(如if enteredDoorCode && passedRetinaScan),又或让 i 值加1的便捷运算符自增运算符++i等. Swift 支持大部分标准 C 语言的运算符,且改进许多特性来减少常规编码错误.如,赋值符(=)不返回值,以防止把想要判断相等运算符(==)的地方写成赋值符导致的错误.数值运算符(+,-,*,/,%等)会检

Swift编程语言学习——类型安全和类型推测

Swift 是一种类型安全(type safe )的语言.类型安全的语言可以让你清楚地知道代码要处理的值的类型.如果你的代码需要一个String,你绝对不可能不小心传进去一个Int. 由于 Swift 是类型安全的,所以它会在编译你的代码时进行类型检查(type checks),并把不匹配的类型标记为错误.这可以让你在开发的时候尽早发现并修复错误. 当你要处理不同类型的值时,类型检查可以帮你避免错误.然而,这并不是说你每次声明常量和变量的时候都需要显式指定类型.如果你没有显式指定类型,Swift

Swift编程语言学习——注释、分号、整数、浮点数

注释 请将你的代码中的非执行文本注释成提示或者笔记以方便你将来阅读.Swift 的编译器将会在编译代码时自动忽略掉注释部分. Swift 中的注释与C 语言的注释非常相似.单行注释以双正斜杠作(//)为起始标记: // 这是一个注释 你也可以进行多行注释,其起始标记为单个正斜杠后跟随一个星号(/*),终止标记为一个星号后跟随单个正斜杠(*/): /* 这是一个, 多行注释 */ 与C 语言多行注释不同,Swift 的多行注释可以嵌套在其它的多行注释之中.你可以先生成一个多行注释块,然后在这个注释

Swift 编程语言学习——Swift简介

有的时候,觉得看英文文档有些费时,看中文文档怕翻译不准,有些地方确实不需要抠字眼,当有些地方如果翻译不精准会产生歧义,所以用这样对照的方式,顺便学习一下Swift. Swift is a new programming language for iOS and OS X apps that builds on the best of C and Objective-C, without the constraints of C compatibility. Swift adopts safe p