100 Days of SwiftUI - Day 12 Optionals 可選類(lèi)型

為了解決空引用的問(wèn)題,Swift使用Optionals解決方案。

1.處理丟失的數(shù)據(jù)

我們使用Int類(lèi)型的age屬性來(lái)保存用戶(hù)的年齡,但有時(shí)候我們不知道用戶(hù)的年齡,該怎么辦?
存儲(chǔ)為0,或者-1表示未知,這兩個(gè)數(shù)字都是不太可能的。
Swift的解決方案是Optionals,使類(lèi)型變?yōu)榭蛇x。

var age: Int? = nil
age = 38

如果我們知道年齡,可以使用它。

為什么Swift有可選類(lèi)型?
在Swift中任何數(shù)據(jù)類(lèi)型都可以是可選的。

2.解包 if let

展開(kāi)可選內(nèi)容的一種常見(jiàn)方法是使用if let語(yǔ)法

if let unwrapped = name {
    print("\(unwrapped.count) letters")
} else {
    print("Missing name.")
}

可選值最重要的功能之一,Swift不允許我們?cè)诓幌日归_(kāi)它們的情況下使用它們。
這為我們所有的應(yīng)用程序提供了極大的保護(hù),因?yàn)樗柚沽瞬淮_定性:當(dāng)您處理一個(gè)字符串時(shí),您知道它是有效的字符串,當(dāng)您調(diào)用一個(gè)返回整數(shù)的函數(shù)時(shí),就可以立即安全地進(jìn)行操作。而且,當(dāng)您的代碼中確實(shí)包含可選內(nèi)容時(shí),Swift會(huì)始終確保正確處理它們-您檢查并解開(kāi)它們,而不僅僅是將不安全的值與已知的安全數(shù)據(jù)混合。

3.guard let

func greet(_ name: String?) {
    guard let unwrapped = name else {
        print("You didn't provide a name!")
        return
    }

    print("Hello, \(unwrapped)!")
}

使用guard let, 可以在功能開(kāi)始前處理問(wèn)題,然后立即退出。意味著函數(shù)的其余部分是正確的,代碼將采用。

使用guard let 還是 if let?

guard在方法開(kāi)始時(shí),會(huì)使用一次或多次,它用于驗(yàn)證條件是否正確。如果想拆開(kāi)可選類(lèi)型,請(qǐng)使用if let ,如果想檢查條件,可以使用guard let。

4.強(qiáng)制解包

當(dāng)你可以確定值不是nil時(shí),你可以將可選類(lèi)型轉(zhuǎn)為非可選類(lèi)型。

let str = "5"
let num = Int(str)!

這時(shí)是確定不為空的,但如果你錯(cuò)了,代碼將崩潰。
因此只有確定它是安全時(shí),才可以使用強(qiáng)制解包。

什么時(shí)候采用強(qiáng)制解包?

即使您99.999%確信它是安全的,也不應(yīng)使用它

5.隱式解包

與常規(guī)的可選類(lèi)型不同,使用時(shí)你不需要解包。

let age: Int! = nil

使用它們不需要 if letguard let
當(dāng)它們沒(méi)有值時(shí),使用它代碼會(huì)崩潰。
使用隱式解包主要是UIKit框架中使用,布局中不會(huì)立即創(chuàng)建控件,延遲到用戶(hù)顯示時(shí)。
而在SwiftUI中,這樣的方式已經(jīng)消失了,隱式解包不再重要。

6.nil合并運(yùn)算符

解包可選值,如果有則返回內(nèi)部值,如果沒(méi)有值,則使用默認(rèn)值。

let user = username(for: 15) ?? "Anonymous"

7.可選鏈

let surnameLetter = names["Vincent"]?.first?.uppercased() ?? "?"

8.try?

do try catch

enum PasswordError: Error {
    case obvious
}

func checkPassword(_ password: String) throws -> Bool {
    if password == "password" {
        throw PasswordError.obvious
    }

    return true
}

do {
    try checkPassword("password")
    print("That password is good!")
} catch {
    print("You can't use that password.")
}

使用try?來(lái)代替try

if let result = try? checkPassword("password") {
    print("Result was \(result)")
} else {
    print("D'oh.")
}

使用try!
如果可以確保函數(shù)不會(huì)失敗可以使用try!

try! checkPassword("sekrit")
print("OK!")

什么時(shí)候使用try?
如果只關(guān)注函數(shù)成功或失敗,使用try?是很好的選擇。

9.init?()

struct Person {
    var id: String

    init?(id: String) {
        if id.count == 9 {
            self.id = id
        } else {
            return nil
        }
    }
}

初始化方法失敗時(shí),對(duì)象創(chuàng)建失敗。你也可以將驗(yàn)證放到一個(gè)單獨(dú)的方法中,但是你很可能忘記調(diào)用它,放入初始化程序中安全的多。

10. as?

當(dāng)你知道某些對(duì)象的類(lèi)型時(shí),你可以對(duì)其進(jìn)行類(lèi)型轉(zhuǎn)換,使用as?,轉(zhuǎn)換失敗時(shí)返回nil。

let pets = [Fish(), Dog(), Fish(), Dog()]
for pet in pets {
    if let dog = pet as? Dog {
        dog.makeNoise()
    }
}

11.總結(jié)

1.可選類(lèi)型使我們以清晰明確的方式表示值的缺失。
2.Swift不允許我們使用未解包的可選類(lèi)型,你可以使用if letguard let解包
3.你可以強(qiáng)制解包,但是如果值為nil時(shí),會(huì)崩潰。
4.隱式解包類(lèi)型不會(huì)像可選類(lèi)型一樣檢查安全。
5.nil合并運(yùn)算來(lái)解包可選值,沒(méi)有則使用默認(rèn)值。
6.可選鏈?zhǔn)刮覀兛梢跃帉?xiě)代碼操作可選類(lèi)型,如果結(jié)果為空,代碼忽略。
7.使用try?會(huì)將throwing函數(shù)轉(zhuǎn)換為可選的返回值。或者使用try!,注意崩潰。
8.如果在初始化時(shí)加入錯(cuò)誤檢查,可以使用init?()。
9.使用類(lèi)型轉(zhuǎn)換將一種類(lèi)型轉(zhuǎn)換為另一種類(lèi)型。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容