/**
1.可選鏈可替代強制解析
2.爲可選鏈定義模型類
3.通過可選鏈調用屬性
4.通過可選鏈調用方法
5.使用可選鏈調用子腳本
6.連接多層鏈接
7.鏈接自判斷返回值的方法
可選鏈是一種可以請求和調用屬性、方法及子腳本的過程,它的自判斷性體現於請求或調用的目標當前可能爲空(nil)。如果自判斷的目標有值,那麼調用就會成功;相反,如果選擇的目標爲空,則這種調用將返回空。多次請求或調用可以被鏈接在一起形成一個鏈,如果任何一個節點爲空將導致整個鏈失效
swift的自判斷鏈和OC中的消息爲空有些相像,但是swift可以使用在任意類型中,並且失敗與否可以被檢測到
*/
//可選鏈可替代強制解析
class Person {
var residence: Residence?
}
class Residence {
var numberOfRoom = 1;
}
let john = Person();
john.residence = Residence();
if let roomCount = john.residence?.numberOfRoom{
//判斷如果residence存在則取回numberOfRoom的值
// print("John's residence has \(roomCount) room(s).");
}else{
// print("Unable to retrieve the number of rooms.")
}
//print(roomCount);
/**
residence爲可選值,未賦值,默認初始化爲nil
*/
class Person {
var residence: Residence?
init(residence: Residence) {
self.residence = residence;
}
}
class Residence {
var numberOfRoom = 1;
}
let john = Person(residence: Residence());
let roomCount = john.residence!.numberOfRoom;
print(roomCount);
//爲可選鏈定義模型類
/**
可以使用可選鏈來多層調用屬性,方法和子腳本。可以利用它們之間的複雜模型來獲取更底層的屬性,並檢查是否可以成功獲取此類底層屬性
*/
class Room2 {
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 Person2 {
var residence: Residence2?;
}
class Residence2 {
var rooms = [Room2]();
var numberOfRooms: Int {
return rooms.count;
}
subscript(i: Int) -> Room2 {
return rooms[i];
}
func printNumberOfRooms() {
print("The number of rooms is \(numberOfRooms)");
}
var address: Address?;
}
//通過可選鏈調用屬性
let john2 = Person2();
if let roomCount = john2.residence?.numberOfRooms {
print("John2's residence has \(roomCount) room(s).");
}else{
print("Unable to retrieve the number of rooms.");
}
//通過可選鏈調用方法
if john2.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.");
}
//通過可選鏈調用子腳本
/**
當使用可選鏈來獲取子腳本的時候,應該將問號放在子標本括號的前面而不是後面,可選鏈的問號一般直接跟在自判斷表達語句的後面
*/
let johnsHouse = Residence2();
johnsHouse.rooms.append(Room2(name: "Living Room"));
johnsHouse.rooms.append(Room2(name: "Kitchen"));
john2.residence = johnsHouse;
if let firstRoomName = john2.residence?[0].name {
print("The first room name is \(firstRoomName)");
}else{
print("Unable to retrieve the first room name");
}
//連接多層連接
/**
可以將多層可選鏈接連接在一起,可以掘取模型內更下層的屬性方法和子腳本。然而多層可選鏈不能再添加比已經返回的可選值更多的層。也就是說:如果試圖獲得的類型不是可選類型,由於使用了可選鏈它將變成可選類型。如果你試圖獲得的類型已經是可選類型,由於可選鏈它也不會提高自判斷性。
因此:如果試圖通過可選鏈獲得Int值,不論使用了多少層鏈接返回的總是Int?。相似的,如果試圖通過可選鏈獲得Int?值,不論使用了多少層鏈接返回的總是Int?.
*/
let johnsAddress = Address();
johnsAddress.buildingName = "The Larches";
johnsAddress.street = "Laurel Street";
john2.residence!.address = johnsAddress;
if let johnsStreet = john2.residence?.address?.street {
print("John2's street name is \(johnsStreet).");
}else{
print("Unable to retrieve the address.");
}//"!"在定義address實例時使用(john2.residence.address)。john2.residence屬性是一個可選類型,因此需要在它獲取address屬性之前使用!解析以獲得它的實際值
//鏈接自判斷返回值的方法
/**
可以通過調用返回可選類型值的方法並按需鏈接方法的返回值
*/
if let buildingIdentifier = john2.residence?.address?.buildingIdentifier() {
print("John2's building identifier is \(buildingIdentifier).");
}
//如果還想進一步對方法返回值執行可選鏈,將可選鏈問號符放在方法括號的後面
/**
將可選鏈問號符放在括號後面是因爲想要鏈接的可選值是方法的返回值,而不是方法本身
*/
if let upper = john2.residence?.address?.buildingIdentifier()?.uppercaseString {
print("John's uppercase building identifier is \(upper).");
}