swift-03-可選項&可選鏈

最近在學習swift,期間也看了不少教程和大神的博客,最後把筆記放這裏,方便查看複習~swift

附上學習資料地址:w3cschool-Swift 教程YungFan大神的簡書(推薦看一下,有些知識點總結地簡直通俗易懂)數組

1、可選項

一、介紹

通俗一點來說,swift中的可選項與nil有關。安全

由於swift是強類型語言,nil也是一個特殊類型,因此說其餘類型的數據不能直接賦值爲nilmarkdown

若是遇到不肯定是否有值的類型,可使用可選項,那麼這個類型只能兩個取值:ni 或者 有一個肯定的值app

二、格式

常規寫法ide

var name: Optional<String>
複製代碼

經常使用語法糖的寫法oop

//注意:在類型和 ? 之間沒有空格
var name: String? 
複製代碼

三、簡單使用

給可選類型賦值學習

//聲明一個可選項
var str: String? = nil
//賦值
str = "hello"
複製代碼

取值ui

print(str) //Optional("hello")
複製代碼

強制解包(!)取值url

//注意:這種作法不安全,只能用於 已經肯定str真的有值的狀況,不然會崩潰 
print(str!) //hello
複製代碼

強制解包安全作法

if str != nil {
    print(str!) //hello
}
複製代碼

隱式解包

if let newStr = str {
    //此時輸出的就是str的值,而不是Optional str
    print(newStr) //hello
}else{
    print("這個值是nil")
}
複製代碼

守衛語句解包

//判斷當語句=false,也就是newStr = nil,直接執行return,也有效防止了崩潰
guard let newStr = str else{
    return
}
print(newStr)
複製代碼

四、應用場景

用可選項來接收URL,讓代碼更加嚴謹

// 正確寫法:使用可選類型來接收
let url : URL? = URL(string: "https://www.baidu.com")
// 也能夠這麼寫:該方式利用類型推斷
let url1 = URL(string: "https://www.baidu.com")

// 經過url來建立request對象:在使用可選類型前要先進行判斷是否有值
// 該語法成爲可選綁定(若是url有值就解包賦值給tempURL,而且執行{})
if let tempUrl = url {
    let request = URLRequest(url: tempUrl)
}
複製代碼

五、代碼示例

/*
 主要做用於值缺失的狀況,相似oc中某個對象=nil,在swift中只有可選項的常量或者變量才能使用nil
 可選項的標誌:?

 nil:
 oc中,表示一個指向不存在對象的指針
 swift中,表示一種特殊類型,值缺失(不只僅對象類型,任何類型的可選項都能置爲nil)
 */
var code: Int? = 100
code = nil
/*
var name: Int = 1000
name = nil
這種狀況會報錯,不是可選項
*/

/*
 使用感嘆號:!
 一旦咱們知道可選項確定有一個值,那麼爲了拿到這個值,就要在可選項以後加上"!"來取值
 */
var age: Int? = 18
print("可選項確定有一個值:\(age!)")
        
複製代碼

2、可選鏈

一、介紹

可選鏈 (Optional Chaining) 是一種能夠請求和調用屬性、方法和子腳本的過程,用於請求或調用的目標可能爲nil。

可選鏈返回兩個值:

  • 若是目標有值,調用就會成功,返回該值
  • 若是目標爲nil,調用將返回nil

屢次請求或調用能夠被連接成一個鏈,若是任意一個節點爲nil將致使整條鏈失效。

二、使用

經過在屬性、方法、或下標腳本的可選值後面放一個問號(?),便可定義一個可選鏈。

2.1 可選鏈可替代強制解析

使用可選鏈'?': 將'?'放在可選值後面來調用方法、屬性、下標腳本,當可選爲nil的時候 輸出比較友好的錯誤信息

使用強制解析'!': 將'!'放在可選值後面來調用方法、屬性、下標腳本,用於強制展開值,當可選爲nil的時候 強制展開會執行錯誤

代碼示例:

class Residence {
    var numberOfRooms = 1
}

class Person {
    var residence: Residence?
}

let john = Person()

// ! 將致使運行時錯誤 :Fatal error: Unexpectedly found nil while unwrapping an Optional value (致命錯誤:在展開可選值時意外發現nil)
let roomCount = john.residence!.numberOfRooms

// ?連接可選residence?屬性,若是residence存在則取回numberOfRooms的值
if let roomCount = john.residence?.numberOfRooms {
    print("John 的房間號爲 \(roomCount)。")
} else {
    print("不能查看房間號")
}

打印:不能查看房間號
複製代碼
2.2 可選鏈的調用

首先定義了4個類,包含了一個多層可選鏈

class Person {
    //住宅
    var residence: Residence?
}


class Residence {
    // 定義了一個變量 rooms,它被初始化爲一個Room[]類型的空數組
    var rooms = [Room]()
    var numberOfRooms: Int {
        return rooms.count
    }
    subscript(i: Int) -> Room {
        return rooms[i]
    }
    func printNumberOfRooms() {
        print("房間號爲 \(numberOfRooms)")
    }
    var address: Address?
}

// Room 定義一個name屬性和一個設定room名的初始化器
class Room {
    let name: String
    init(name: String) { self.name = name }
}

// 模型中的最終類叫作Address
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
        }
    }
}
複製代碼
2.2.1 經過可選鏈調用方法
let john = Person()

if john.residence?.printNumberOfRooms() != nil {
    print("輸出房間號")
} else {
    print("沒法輸出房間號")
}

打印:沒法輸出房間號
複製代碼
2.2.2 經過可選鏈調用下標腳本

咱們能夠經過可選鏈來獲取下標腳本的值,可是不能經過可選鏈來設置下標腳本

let john = Person()

//?在這個位置的緣由是:john.residence 是可選鏈試圖得到的可選值
if let firstRoomName = john.residence?[0].name {
    print("第一個房間名 \(firstRoomName).")
} else {
    print("沒法檢索到房間")
}
複製代碼

再來看看給 john 賦個值

let john = Person()

let johnsHouse = Residence()
johnsHouse.rooms.append(Room(name: "客廳"))
johnsHouse.rooms.append(Room(name: "廚房"))

john.residence = johnsHouse
 
let johnsAddress = Address()
johnsAddress.buildingName = "A123"
johnsAddress.street = "A123 Street"

john.residence!.address = johnsAddress

//獲取下標腳本
if let firstRoomName = john.residence?[0].name {
    print("第一個房間名爲\(firstRoomName)")
} else {
    print("沒法檢索到房間")
}

//打印:第一個房間名爲客廳


//兩層可選鏈
if let johnsStreet = john.residence?.address?.street {
    print("John 所在的街道是 \(johnsStreet)。")
} else {
    print("沒法檢索到地址。 ")
}

//打印:John 所在的街道是 A123 Street
複製代碼
相關文章
相關標籤/搜索