import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//可空链式调用
//可空链式是一种可以请求和调用属性、方法及下标的过程,它的可空性体现于请求或调用的目标当前可能为空nil。如果可空的目标有值,那么调用就会成功;如果选择的目标为空,那么这种调用将返回空。多个连续的调用可以被链接在一起形成一个调用链,如果其中一个节点为空将导致整个链调用失败
//可空链式调用的返回结果与原本的返回结果具有相同的类型,但是被包装成了一个可空类型值。当可空链式调用成功时,一个本应该返回Int的类型的结果将会返回Int?类型
// let john = Person()
// let roomCount = john.residence!.numberOfRooms
// //报错:unexpectedly found nil while unwrapping an Optional value
//可空链式调用提供了另一种访问numberOfRooms的方法,使用问号?来代替原来的叹号的位置
let join = Person()
if let roomCount = join.residence?.numberOfRooms{
print("John residence has \(roomCount) rooms")
}else{
print("Unable to retrive the number of rooms");
}//Unable to retrive the number of rooms
//在residence后面添加问号之后,swift就会在residence 不为空的情况下访问numberOfRooms
//值得注意的是即使numberOfRooms是不可空的Int时这一点也成立。只要是通过可空链式调用就意味着最后numberOfRooms返回一个Int?而不是Int
//通过可空链式调用访问属性
if join.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")
}//It was not possible to print the number of rooms
//通过可空链式调用来访问下标
//当通过可空链式调用访问可空值的下标的时候,应该将问号放在下标方括号的前面而不是后面。
if let firstRoomName = join.residence?[0].name{
print("The first room name is \(firstRoomName)")
}else{
print("unable to retrieve the first room name")
}//unable to retrieve the first room name
join.residence?[0]=Room(name: "Bath")
//这次赋值同样失败,因为residence目前是nil
let johnsHouse = Residence()
johnsHouse.rooms.append(Room(name: "LivingRoom"))
johnsHouse.rooms.append(Room(name: "Kitchen"))
join.residence = johnsHouse
if let firstRoomName = join.residence?[0].name{
print("The first room is \(firstRoomName)")
}else{
print("Unable to retrieve the first room name")
}//The first room is LivingRoom
//访问可空类型的下标
var testScores = ["Dave":[86,82,84],"Bev":[79,94,81]]
testScores["Dave"]?[0] = 91
testScores["Bev"]?[0]++
testScores["Brian"]?[0] = 72
print("\(testScores)");//["Bev": [80, 94, 81], "Dave": [91, 82, 84]]
//多层链接
//可以通过多个链接多个可空链式调用来向下访问属性,方法以及下标。但是多层可空链式调用不会添加返回值的可空性
//通过可空链式调用访问一个Int值,将会返回Int?,不管进行了多少次可空链式调用
//类似的,通过可空链式调用访问Int?值,并不会变的更加可空
if let joinsStreet = join.residence?.address?.street{
print("join street name is \(joinsStreet)")
}else{
print("Unable to retrieve the address")
}//Unable to retrieve the address
let johnsAddress=Address()
johnsAddress.buildingName="The Larches"
johnsAddress.street="Laurel Street"
join.residence?.address=johnsAddress
if let johnsStreet=join.residence?.address?.street{
print("John street name is \(johnsStreet)")
}else{
print("Unable to retrieve the address")
}//John street name is Laurel Street
//对返回可空值的函数进行链接
if let buildingIdentifier = join.residence?.address?.buildingIdentifier(){
print("Join building identifier is \(buildingIdentifier)")
}//Join building identifier is The Larches
if let beginsWithThe = join.residence?.address?.buildingIdentifier()?.hasPrefix("The"){
print("john building identifier begins with \"the\"")
}else{
print("not begin with \"the\"")
}//john building identifier begins with "the"
//buildingIdentifier()?的返回值是可空值,而不是方法本身是可空的
}
}
class Person {
var residence:Residence?
}
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 != nil{
return buildingName
}else if buildingNumber != nil{
return buildingNumber
}else{
return nil
}
}
}
class Residence {
var rooms=[Room]()//初始化一个数组
var address: Address?
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)")
}
}