TAG

RSS订阅

收藏本站

设为首页

当前位置:主页 > 移动开发 > IOS开发 >

Swift语法:可选链接(Optional Chaining)

发布时间:2016-03-18 21:58 类别:IOS开发

1、引言

可选链接是一个可以请求和调用可选目标(该目标可能为 nil)的属性、方法或者下标的过程。

2、为什么会有可选链接?

我们先来看一个示例:
[objc] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. class Residence {  
  2.     var numberOfRooms = 1  
  3. }  
  4. class Person {  
  5.     var residence: Residence?  
  6. }  
  7.   
  8. let john = Person()  
  9. // let roomCount = john.residence!.numberOfRooms  
  10. // 由于 john.residence 为 nil,通过声明符(!)强制获得 numberOfRooms 属性会编译出错  
  11.   
  12. let residence = Residence()  
  13. let jack = Person()  
  14. jack.residence = residence  
  15. let roomCount = jack.residence!.numberOfRooms   
  16. // 只有当 jack.residence 不是 nil 时才能运行通过  
为了解决上述 jack.residence 可能为空而又必须获取 numberOfRooms 值的场景,可选链接提供了一种方法:通过(?)替代上述的(!)。
[objc] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. let john = Person()   
  2. let roomCount = john.residence?.numberOfRooms   
  3. // 虽然此时 jack.residence 为 nil,但是运行通过  
注意:通过调用可选链接的返回结果与原本的返回结果具有相同的类型,但是将原本的返回结果包装成了一个可选的。
如:可选链接调用成功时原本应该返回(someType)的属性将会返回(someType?)。
叹号(!)和问号(?)的区别:
叹号(!):强制解析符号。如果解析对象为 nil 会编译出错。
问号(?):可选链接符号。就算解析对象为 nil 也可运行,但是返回结果为 nil。

3、可选链接的运用

[objc] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. class Room {  
  2.     let name: String  
  3.     init(name: String) { self.name = name }  
  4. }  
  5. class Address {  
  6.     var buildingName: String?  
  7.     var buildingNumber: String?  
  8.     var street: String?  
  9.     func buildingIdentifier() -> String? {  
  10.         if buildingName != nil {  
  11.             return buildingName  
  12.         } else if buildingNumber != nil {  
  13.             return buildingNumber  
  14.         } else {  
  15.             return nil  
  16.         }  
  17.     }  
  18. }  
  19. class Residence {  
  20.     var rooms = [Room]()  
  21.     var address: Address?  
  22.     var numberOfRooms: Int {  
  23.         return rooms.count  
  24.     }  
  25.     func printNumberOfRooms() {  
  26.         println("The number of rooms is \(numberOfRooms)")  
  27.     }  
  28.     subscript(i: Int) -> Room {  
  29.         get {  
  30.             return rooms[i]  
  31.         }  
  32.         set {  
  33.             rooms[i] = newValue  
  34.         }  
  35.     }  
  36. }  
  37. class Person {  
  38.     var residence: Residence?  
  39. }  
  40.   
  41. // 1、通过可选链接调用属性和设置属性  
  42. let john = Person()  
  43. if let roomCount = john.residence?.numberOfRooms {  
  44.     println("John's residence has \(roomCount) room(s).")  
  45. else {  
  46.     println("Unable to retrieve the number of rooms.")  
  47. }  
  48. // prints "Unable to retrieve the number of rooms."  
  49. let someAddress = Address()  
  50. someAddress.buildingNumber = "29"  
  51. someAddress.street = "Acacia Road"  
  52. john.residence?.address = someAddress  
  53. // 运行通过,但是由于 residence 为 nil,所以设置失败  
  54.   
  55. // 2、通过可选链接调用方法  
  56. if john.residence?.printNumberOfRooms() != nil {  
  57.     println("It was possible to print the number of rooms.")  
  58. else {  
  59.     println("It was not possible to print the number of rooms.")  
  60. }  
  61. // prints "It was not possible to print the number of rooms."  
  62. if (john.residence?.address = someAddress) != nil {  
  63.     println("It was possible to set the address.")  
  64. else {  
  65.     println("It was not possible to set the address.")  
  66. }  
  67. // prints "It was not possible to set the address."  
  68.   
  69. // 3、通过可选链接调用下标和设置值  
  70. if let firstRoomName = john.residence?[0].name {  
  71.     println("The first room name is \(firstRoomName).")  
  72. else {  
  73.     println("Unable to retrieve the first room name.")  
  74. }  
  75. // prints "Unable to retrieve the first room name."  
  76. john.residence?[0] = Room(name: "Bathroom")  
  77. // 运行通过,设置失败  
  78.   
  79. // 补充:可选类型调用下标  
  80. var testScores = ["Dave": [8682, 84], "Bev": [7994, 81]]  
  81. testScores["Dave"]?[0] = 91  
  82. testScores["Bev"]?[0]++  
  83. testScores["Brian"]?[0] = 72  
  84.   
  85. // 4、多层可选链接  
  86. if let johnsStreet = john.residence?.address?.street {  
  87.     println("John's street name is \(johnsStreet).")  
  88. else {  
  89.     println("Unable to retrieve the address.")  
  90. }  
  91. // prints "Unable to retrieve the address."  
  92.   
  93. let johnsHouse = Residence()  
  94. johnsHouse.rooms.append(Room(name: "Living Room"))  
  95. john.residence = johnsHouse  
  96.   
  97. let johnsAddress = Address()  
  98. johnsAddress.buildingName = "The Larches"  
  99. johnsAddress.street = "Laurel Street"  
  100. john.residence!.address = johnsAddress  
  101.   
  102. if let johnsStreet = john.residence?.address?.street {  
  103.     println("John's street name is \(johnsStreet).")  
  104. else {  
  105.     println("Unable to retrieve the address.")  
  106. }  
  107. // prints "John's street name is Laurel Street."  
  108.   
  109. // 5、可选链接返回方法的值  
  110. if let buildingIdentifier = john.residence?.address?.buildingIdentifier() {  
  111.     println("John's building identifier is \(buildingIdentifier).")  
  112. }  
  113. // prints "John's building identifier is The Larches."  
  114.   
  115. if let beginsWithThe = john.residence?.address?.buildingIdentifier()?.hasPrefix("The") {  
  116.     if beginsWithThe {  
  117.         println("John's building identifier begins with \"The\".")  
  118.     } else {  
  119.         println("John's building identifier does not begin with \"The\".")  
  120.     }  
  121. }  
  122. // prints "John's building identifier begins with "The"."  
仔细观察上述示例,可能有人会对调用下标 john.residence?[0].name 和返回方法的值 john.residence?.address?.buildingIdentifier()?.hasPrefix("The") 中(?)的位置有疑惑:
A、调用下标中的解释:因为可选链接的问号一般直接跟在可选表达语句的后面。
B、返回方法的值中的解释:你想要的是 buildingIdentifier 方法的返回值,而不是方法本身。

4、结语

文章最后更新时间:2015年2月3日09:37:48。
欲了解更细致的请参考官方文档:Optional Chaining

转载请声明出处:http://blog.csdn.net/jinnchang/article/details/43370557
猜你会喜欢....

Copyright © 2015 www.wahenzan.com 哇!很赞 版权所有 浙ICP备14030256号-1 Power by DedeCms

浙公网安备 33010602005986号

声明:本站所有文章除标明原创外,均来自网络转载,版权归原作者所有,如果有侵犯到您的权益,请联系本站删除 网站管理员:758763728

360网站安全检测平台