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

简介: 在值可能不存在的情况下使用可选值(optional), 可选值是:   · 存在一个值,这个值等于 x 或   · 不存在任何值  注: 在 C 和 Objective-C 中可选值的概念并不存在。

在值可能不存在的情况下使用可选值(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

 

 

 

 

 

目录
相关文章
|
6月前
|
Swift iOS开发
Swift 语言: 什么是协议(Protocol)?如何实现和使用协议?
Swift 语言: 什么是协议(Protocol)?如何实现和使用协议?
184 2
|
6月前
|
存储 安全 Swift
Swift 语言:什么是 Swift 的泛型(Generics)?
Swift 语言:什么是 Swift 的泛型(Generics)?
83 0
|
2月前
|
存储 安全 Swift
Swift 语言为公司电脑管理软件带来新机遇
在数字化时代,公司电脑管理软件的重要性日益凸显,Swift 语言为其带来了全新机遇。Swift 语言具备简洁、安全和高效的特点,易于学习且能有效防止程序错误和漏洞,同时充分利用硬件资源,提升程序运行速度。通过 Swift,我们可以编写代码以获取硬件信息、管理软件安装与卸载,甚至实现远程控制和数据加密等功能,极大地提高了管理效率和数据安全性,为公司电脑管理提供了强大的支持。未来,Swift 语言有望助力开发综合性电脑管理平台,集成多种功能,进一步提升工作效率和数据保护能力。
43 4
|
8天前
|
安全 API Swift
探索iOS开发中的Swift语言之美
【10月更文挑战第23天】在数字时代的浪潮中,iOS开发如同一艘航船,而Swift语言则是推动这艘船前进的风帆。本文将带你领略Swift的独特魅力,从语法到设计哲学,再到实际应用案例,我们将一步步深入这个现代编程语言的世界。你将发现,Swift不仅仅是一种编程语言,它是苹果生态系统中的一个创新工具,它让iOS开发变得更加高效、安全和有趣。让我们一起启航,探索Swift的奥秘,感受编程的乐趣。
|
30天前
|
安全 Swift iOS开发
探索iOS开发中的Swift语言之美
在数字时代的浪潮中,移动应用已成为日常生活的延伸。本文将深入探讨iOS平台上的Swift编程语言,揭示其背后的设计哲学、语法特性以及如何利用Swift进行高效开发。我们将通过实际代码示例,展示Swift语言的强大功能和优雅简洁的编程风格,引导读者理解并运用Swift解决实际问题。
|
2月前
|
安全 Swift iOS开发
探索iOS开发之旅:Swift语言的魅力与挑战
【9月更文挑战第21天】在这篇文章中,我们将一起潜入iOS开发的海洋,探索Swift这门现代编程语言的独特之处。从简洁的语法到强大的功能,Swift旨在让开发者能够以更高效、更安全的方式构建应用程序。通过实际代码示例,我们会深入了解Swift如何简化复杂任务,并讨论它面临的挑战和未来的发展方向。无论你是初学者还是有经验的开发者,这篇文章都将为你提供新的视角和知识。
44 4
|
4月前
|
安全 编译器 Swift
探索iOS开发:Swift语言的现代魔法
【7月更文挑战第11天】本文深入探讨了Swift编程语言,它如何革新iOS开发领域,以及它为开发者带来的独特优势。我们将从Swift的基础语法出发,通过实际案例分析其性能优化技巧,最后讨论Swift在跨平台开发中的潜力。文章旨在为读者提供一个全面而深入的视角,了解Swift不仅仅是一门语言,更是一种推动创新的力量。
|
6月前
|
安全 Swift Android开发
构建移动应用:Swift vs Kotlin —— 两大主流语言的对决
【5月更文挑战第11天】Swift与Kotlin在移动应用开发中各有优势。Swift是iOS开发的首选,以其简洁语法、高性能和类型安全著称;而Kotlin是Android的官方推荐语言,以其与Java的无缝互操作、空安全特性和简洁代码受到青睐。两者在语法简洁性、性能和社区支持上表现优秀,但平台兼容性不同。开发者应根据项目需求和目标平台选择合适的语言。
|
6月前
|
安全 Swift iOS开发
【Swift 开发专栏】Swift 语言入门指南
【4月更文挑战第30天】Swift是苹果公司的现代编程语言,以其高效、安全和简洁深受喜爱。它融合了类型推断、闭包和泛型等特性,提供强大的内存管理,支持iOS、macOS等多个平台开发。基础语法包括变量、常量、数据类型、运算符和控制流语句。高级特性涵盖函数、闭包、类与结构体、协议以及泛型。学习Swift能为开发者奠定坚实基础。
72 0
|
6月前
|
安全 Swift
Swift 语言:什么是可选类型(Optional)?如何处理可选类型的安全解包?
Swift的可选类型是处理值可能缺失的类,用?表示。它们能表示有值或无值状态。安全解包用`if let`或`guard let`避免崩溃,而强制解包`!`则风险较高,若值为`nil`会触发运行时错误。
45 0