天天看點

用“可選鍊”而不用“強制解包”

用“可選鍊”而不用“強制解包”

class Person{
  var residence: Residence?//residence是住所的意思
}
class Residence{
  var numberOfRoomes = 1
}
           

兩個類“Person”和“Residence“,現在假如我建立了一個新的Person執行個體,他的residence屬性因為是可選值,是以被初始化為nil,如下

如果這時使用感歎号( ! )強制解包numberOfRoomes會因為residence的值為nil而崩潰。

為此,可選鍊式調用提供了另一種通路numberOfRooms的方式,使用( ? )來代替原來的感歎号( ! )

if let roomCount = john.residence?.numberOfRooms{
  print("john's residence has \(roomCount) rooms.")
}else{
  print("Unable to retrieve the number of rooms.")
}
           

字尾問号( ? )的作用是在該值不為nil 的情況下通路,記住上面這種寫法,你可能會經常遇到if let xxx = xxx這種形式

通路失敗(值為nil)時則傳回

  • 看到這裡,你已經完成了對基礎鍊式調用理論的學習,不妨看看開發中可能碰到的例子?
class Person {
  var residence: Residence?
}
class Residence {
  var rooms = [Room]()
  var numberOfRooms: Int {
    return rooms.count
  }
class Room {
  let name: String
  init(name: String) {self.name = name}
}
  //subscript是下标的意思:傳入一個下标數字,傳回需要的那個房間
  subscript(i: Int) -> Room {
    get{
      return rooms[i]
    }
    set{
      rooms[i] = newValue
    }
  }
  func printNumberOfRooms() {
    print("The number of rooms is \(numberOfRooms)")
  }
  var address: Address?
}
           

仔細看下代碼!其中Address類會在下方給出,其他應該都能看懂

class Address {
  var buildingName: String?
  var buildNumber: String?
  var street: String?
  func buildingID() -> String? {
    if bildingName != nil {
      return buildingName
    }else if let buildingNumber = buildingNumber, let street = street{
      return "\(buildingNumber \(street))"
    }else{
      return nil
    }
  }
}
           

可以看出Address類中含有大量的可選值,buildingID提供了一個用來表示某個建築方法:如果它有名字那直接傳回名字,如果它沒名字,那就看看它是否同時擁有buildNumber和street,有則傳回一個拼接的字元串沒有則傳回nil

仔細看看黃字是怎麼實作的 ! ! !

  • 好了看完了例子,我想你應該知道該怎麼通路一個可選值了
let john = Person()
if let roomCount = john.residence?.numberOfRooms{
  print("john has \(roomCount)'s rooms")
}else{
	return nil  
}
           

我們對john已經進行了初始化是以residence存在了就可以通路的到