Welcome to FutureAppLaboratory

v=(*^ワ^*)=v

Learning Swift Part 14 - Optional Chaining

| Comments

===== Full Notes =====

Optional Chaining

  • Optional chaining is a process for querying and calling properties, methods, and subscripts on an optional that might currently be nil.

    • If the optional contains a value, the property, method, or subscript call succeeds; if the optional is nil, the property, method, or subscript call returns nil.
    • Multiple queries can be chained together, and the entire chain fails gracefully if any link in the chain is nil.
    • Optional chaining in Swift is similar to messaging nil in Objective-C, but in a way that works for any type, and that can be checked for success or failure.
  • Optional Chaining as an Alternative to Forced Unwrapping

    • Sample of Forced Unwarpping class Person { var residence: Residence? }

          class Residence {
              var numberOfRooms = 1
          }
      
          let john = Persion()
      
          let roomCount = john.residence!.numberOfRooms
          // this triggers a runtime error, because residence maybe nil
      
    • Optional chaining provides an alternative way to access the value of numberOfRooms.

          if let roomCount = john.residence?.numberOfRooms {
              println("John's residence has \(roomCount) room(s).")
          } else {
              println("Unable to retrieve the number of rooms.")
          }
          // prints "Unable to retrieve the number of rooms.
      
          // Even numberOfRooms is Int, optional chaining will always return it as Int?
      
  • Defining Model Classes for Optional Chaining

          class Residence {
              var rooms = Room[]()
              var numberOfRooms: Int {
              return rooms.count
              }
              subscript(i: Int) -> Room {
                  return rooms[i]
              }
              func printNumberOfRooms() {
                  println("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 buildingName {
                      return buildingName
                  } else if buildingNumber {
                      return buildingNumber
                  } else {
                      return nil
                  }
              }
          }
    
  • Calling Properties Through Optional Chaining

    • It is the same as above

          let john = Person()
          if let roomCount = john.residence?.numberOfRooms {
              println("John's residence has \(roomCount) room(s).")
          } else {
              println("Unable to retrieve the number of rooms.")
          }
      
  • Calling Methods Through Optional Chaining

          func printNumberOfRooms() {
              println("The number of rooms is \(numberOfRooms)")
          }
    
          “if john.residence?.printNumberOfRooms() {
              println("It was possible to print the number of rooms.")
          } else {
              println("It was not possible to print the number of rooms.")
          }
          // prints "It was not possible to print the number of rooms.
    
  • Calling Subscripts Through Optional Chaining

          if let firstRoomName = john.residence?[0].name {
              println("The first room name is \(firstRoomName).")
          } else {
              println("Unable to retrieve the first room name.")
          }
          // prints "Unable to retrieve the first room name.
    
  • Linking Multiple Levels of Chaining

    • If the type you are trying to retrieve is not optional, it will become optional because of the optional chaining.
    • If the type you are trying to retrieve is already optional, it will not become more optional because of the chaining.

          “if let johnsStreet = john.residence?.address?.street {
              println("John's street name is \(johnsStreet).")
          } else {
              println("Unable to retrieve the address.")
          }
          // prints "Unable to retrieve the address.”
      
  • Chaining on Methods With Optional Return Values

          if let buildingIdentifier = john.residence?.address?.buildingIdentifier() {
              println("John's building identifier is \(buildingIdentifier).")
          }
          // prints "John's building identifier is The Larches.
    
          “if let upper = john.residence?.address?.buildingIdentifier()?.uppercaseString {
              println("John's uppercase building identifier is \(upper).")
          }
          // prints "John's uppercase building identifier is THE LARCHES.”
    

Comments