美文网首页swift
《Swift从入门到精通》(十四):可选项响应链

《Swift从入门到精通》(十四):可选项响应链

作者: 萧1帅 | 来源:发表于2021-10-14 09:11 被阅读0次
    • 可选项响应链

      • 可选项响应链是一个用于访问和调用属性、方法、下标的过程,这些属性、方法、下标可能为 nil;如果有值就会调用成功,如果响应链中只要有一处为 nil,则整个链就会失败;Swift 中可选项响应链类似于 Objective-C 中传递消息 nil,但其可用于任何类型,并且可以检查成功不是失败。
    • 可选项作为强制解包一种替代方案

      • 示例

        class Person {
            var residence: Residence?
        }
        // 
        class Residence {
            var numberOfRooms = 1
        }
        let john = Person()
        let roomCount = john.residence!.numberOfRooms
        // this triggers a runtime error
        if let roomCount = john.residence?.numberOfRooms {
            print("John's residence has \(roomCount) room(s).")
        } else {
            print("Unable to retrieve the number of rooms.")
        }
        // Prints "Unable to retrieve the number of rooms."
        // 如果你给residence赋值,结果如下
        john.residence = Residence()
        if let roomCount = john.residence?.numberOfRooms {
            print("John's residence has \(roomCount) room(s).")
        } else {
            print("Unable to retrieve the number of rooms.")
        }
        // Prints "John's residence has 1 room(s)."
        
        
    • 为可选项响应链定义模型类

      • 示例代码块
      class Person {
          var residence: Residence?
      }
      class Residence {
          var rooms = [Room]()
          var numberOfRooms: Int {
              return rooms.count
          }
          subscript(i: Int) -> Room {
              get {
                  return rooms[I]
              }
              set {
                  rooms[i] = newValue
              }
          }
          func printNumberOfRooms() {
              print("The number of rooms is \(numberOfRooms)")
          }
          var address: Address?
      }
      class Room {
          let name: String
          init(name: String) { self.name = name }
      }
      class Address {
          var buildingName: String?
          var buildingNumber: String?
          var street: String?
          func buildingIdentifier() -> String? {
              if let buildingNumber = buildingNumber, let street = street {
                  return "\(buildingNumber) \(street)"
              } else if buildingName != nil {
                  return buildingName
              } else {
                  return nil
              }
          }
      }
      
      
    • 通过可选项访问属性

      • 示例代码块
      // 用上面创建的类
      let john = Person()
      if let roomCount = john.residence?.numberOfRooms {
          print("John's residence has \(roomCount) room(s).")
      } else {
          print("Unable to retrieve the number of rooms.")
      }
      // Prints "Unable to retrieve the number of rooms."
      // 通过响应链设置值
      // 由于此之前并没有为residence设值,为nil,因此用someAddress赋值不会成功
      let someAddress = Address()
      someAddress.buildingNumber = "29"
      someAddress.street = "Acacia Road"
      john.residence?.address = someAddress
      // 上面的情况不好观察,下面用函数会比较好观察
      func createAddress() -> Address {
          print("Function was called.")
      //
          let someAddress = Address()
          someAddress.buildingNumber = "29"
          someAddress.street = "Acacia Road"
      //
          return someAddress
      }
      john.residence?.address = createAddress()
      // 可以发现上面的 "Function was called."不会打印
      
      
    • 通过可选项调用方法

      • 示例代码块
      // 本例中方法 printNumberOfRooms() 有一个隐式返回值 `Void` (或者 `()` 即空元组)
      // 如果是可选的值调用,则返回的是 `Void?`,不是 `Void`
      // 因此可以用 `if` 语句来判断方法是否调用成功
      // 
      if john.residence?.printNumberOfRooms() != nil {
          print("It was possible to print the number of rooms.")
      } else {
          print("It was not possible to print the number of rooms.")
      }
      // Prints "It was not possible to print the number of rooms."
      //
      // 如果属性返回是 `Void?`,也可用同样的判断方法
      if (john.residence?.address = someAddress) != nil {
          print("It was possible to set the address.")
      } else {
          print("It was not possible to set the address.")
      }
      // Prints "It was not possible to set the address."
      
      
    • 通过可选项访问下标

      • ? 放在 [] 之前,总是紧跟表达式之后
      if let firstRoomName = john.residence?[0].name {
          print("The first room name is \(firstRoomName).")
      } else {
          print("Unable to retrieve the first room name.")
      }
      // Prints "Unable to retrieve the first room name."
      // `?` 的执行是在紧跟 residence 之后, 在 `[]` 调用之前
      john.residence?[0] = Room(name: "Bathroom")
      // 上面的尝试赋值也会失败,因为 residence 仍然是 nil
      
      
      let johnsHouse = Residence()
      johnsHouse.rooms.append(Room(name: "Living Room"))
      johnsHouse.rooms.append(Room(name: "Kitchen"))
      john.residence = johnsHouse
      // 
      if let firstRoomName = john.residence?[0].name {
          print("The first room name is \(firstRoomName).")
      } else {
          print("Unable to retrieve the first room name.")
      }
      // Prints "The first room name is Living Room."
      
      
      • 可选类型的下标访问,? 要写在 [] 之后
      var testScores = ["Dave": [86, 82, 84], "Bev": [79, 94, 81]]
      testScores["Dave"]?[0] = 91
      testScores["Bev"]?[0] += 1
      testScores["Brian"]?[0] = 72
      // the "Dave" array is now [91, 82, 84] and the "Bev" array is now [80, 94, 81]
      
      
    • 连接多层级的响应链

      • 如果要获取的值不是可选项,但由于可选响应链,它将会成为可选项
      • 如果要获取的值是可选项,也不会因为可选项响应链变成多层可选(类似:??, ???)
      if let johnsStreet = john.residence?.address?.street {
          print("John's street name is \(johnsStreet).")
      } else {
          print("Unable to retrieve the address.")
      }
      // Prints "Unable to retrieve the address."
      // 如果你给 address 赋一个值
      let johnsAddress = Address()
      johnsAddress.buildingName = "The Larches"
      johnsAddress.street = "Laurel Street"
      john.residence?.address = johnsAddress
      // 
      if let johnsStreet = john.residence?.address?.street {
          print("John's street name is \(johnsStreet).")
      } else {
          print("Unable to retrieve the address.")
      }
      // Prints "John's street name is Laurel Street."
      
      
    • 方法返回可选项的响应链

      • 示例代码块
      if let buildingIdentifier = john.residence?.address?.buildingIdentifier() {
          print("John's building identifier is \(buildingIdentifier).")
      }
      // Prints "John's building identifier is The Larches."
      // 要执行更深层的响应链,如下
      if let beginsWithThe =
          john.residence?.address?.buildingIdentifier()?.hasPrefix("The") {
          if beginsWithThe {
              print("John's building identifier begins with \"The\".")
          } else {
              print("John's building identifier does not begin with \"The\".")
          }
      }
      // Prints "John's building identifier begins with "The"."
      // 注意:`?` 是加在 `()` 之后因为返回值才是可选项,而不是方法名之后
      
      

    相关文章

      网友评论

        本文标题:《Swift从入门到精通》(十四):可选项响应链

        本文链接:https://www.haomeiwen.com/subject/nrbsoltx.html