import Foundation
//***********************************************************************************************
//1.Optional Chaining(自判断链接)
//_______________________________________________________________________________________________
//介绍
//自判断链接是一种可以请求和调用属性,方法以及子脚本的过程,他的自判断性体现于请求或者调用的目标当前可能为空。如果自判断的目标有值,那么他的调用就会成功;如果目标为空,返回 nil
//***********************************************************************************************
//2.Optional Chaining as an Alternative to Forced Unwrapping(自判断链接可以替代强制拆包)
//_______________________________________________________________________________________________
//介绍
//通过在想调用属性,方法,或者子脚本的自判断值(非空)后放一个问号,可以定义一个自判断链接。
//_______________________________________________________________________________________________
//代码演示自判断链接和强制拆包的不同
class Person{ //Person 具有一个自判断 residence属性
var residence: Residence?
}
class Residence{ //Residence 具有一个 Int 类型的 numberOfRooms
var numberOfRooms = 1
}
let john = Person() //因为 Person 类中 residence 为自判断型,所以在创建实例的时候 residence属性默认为空
//let roomCount = john.residence!.numberOfRooms //如果我们此刻想要强制拆包的话,因为 john.residence为 nil,程序错误,只有当 john.residence不为空的时候,程序才能运行
if let roomCount =john.residence?.numberOfRooms{ //使用自判断链接提供了另外一种方式去获取类实例属性,这时不会抱错,而是以 nil的形式表示 john.residence
println("john's residence has\(roomCount) room")
}
else{
println("Unable to retrieve the number of rooms")
}
john.residence =Residence() //自己定义一个 Residence 实例给 john.residence , 这时它就不是空了
if let roomCount =john.residence?.numberOfRooms{
println("john's residence has\(roomCount) room")
}
else{
println("Unable to retrieve the number of rooms")
}
//***********************************************************************************************
//3.Defining Model Classes for Optional Chaining(为自判断链接定义模型类)
//_______________________________________________________________________________________________
//介绍
//我们可以使用自判断链接来多层调用属性,方法和子脚本
class Person1{
var residence1: Residence1?
}
class Residence1{
var rooms = [Room]() //初始化 rooms 为一个空数组,存储的元素必须为 Room 类型
var numberOfRooms: Int{
return rooms.count
}
subscript(i:Int) -> Room{ //为了快速访问 rooms 数组, Residence1 定义了一个只读的子脚本,通过插入角标就可以成功调用
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?{
ifbuildingName{
return buildingName
}
else{
return nil
}
}
}
//***********************************************************************************************
//4.Calling Properties Through Optional Chaining(通过自判断链接调用属性)
//_______________________________________________________________________________________________
//代码演示使用自判断链接替代强制拆包获取属性,并且检查属性是否获取成功
let john1 =Person1()
if let roomCount =john1.residence1?.numberOfRooms{ //由于 john1.residence1 为 nil,所以执行 else 中的语句
println("john's residence has\(roomCount) rooms")
}
else{
println("Unabel to retrieve the number of rooms")
}
//***********************************************************************************************
//5.Calling Methods Through Optional Chaining(通过自判断链接调用方法)
//_______________________________________________________________________________________________
//实例代码演示自判断链接调用方法
if john1.residence1?.printNumberOfRooms(){
println("is was possible to print the number of rooms")
}
else{
println("it was not possible to print the number of rooms")
}
//***********************************************************************************************
//6.Calling Subscripts Through Optional Chaining(通过自判断链接调用子脚本)
//_______________________________________________________________________________________________
//实例代码演示通过自判断链接调用子脚本
iflet firstRoomName = john1.residence1?[0].name {
println("The first room is\(firstRoomName)")
}
else{
println("Unable to retrieve the first room name")
}
let Listo =Residence1()
Listo.rooms += Room(name: "Pin")
Listo.rooms += Room(name: "Melody")
john1.residence1 =Listo //给 john1.residence1 创建实例
iflet firstRoomName = john1.residence1?[0].name{
println("the first room is\(firstRoomName)")
}
else{
println("Unable to retrieve the first room name")
}
//***********************************************************************************************
//7.CLinking Multiple Levels of Chaining(连接多层链接)
//_______________________________________________________________________________________________
//代码演示连接多层链接
if let johnsStreet =john1.residence1?.address?.street{ //此时 john1.residence1不是 nil,但 john1.residence1.address为 nil,所以返回 else语句
println("john's street name is\(johnsStreet)")
}
else{
println("Unable to retrieve the address")
}
let address =Address()
address.buildingName ="The Larches"
address.street ="laurel Street"
john1.residence1!.address =address //为 john1.residence1.address赋值
if let johnsStreet =john1.residence1?.address?.street{ //此时 john1.residence1不是 nil,但 john1.residence1.address为 nil,所以返回 else语句
println("john's street name is\(johnsStreet)")
}
else{
println("Unable to retrieve the address")
}
//***********************************************************************************************
//8.Chaining on Methods With Optional Return Values(链接自判断返回值的方法)
//_______________________________________________________________________________________________
//代码实例演示自判断连接的返回值方法
iflet buildingIdentifier = john1.residence1?.address?.buildingIdentifier(){
println("john's building identifier is\(buildingIdentifier)") //返回的值依旧是 String类型的自判断链接
}
iflet buildingIdentifier = john1.residence1?.address?.buildingIdentifier()?.uppercaseString{ //当继续对自判断链接执行操作室,使用 ?.来间隔方法
println("john's building identifier is\(buildingIdentifier)") //返回的值依旧是 String类型的自判断链接
}