第三十一章 Swift Error

Swift Error只是個協(xié)議,不能直接使用傳地址的方式傳遞協(xié)議Error,
他可以通過asNSError互相轉(zhuǎn)化乡范。

public protocol Error {
}

extension Error {
}

extension Error where Self : RawRepresentable, Self.RawValue : FixedWidthInteger {
}

可以發(fā)現(xiàn)什么都沒有暴露出來,但它其實有我們最常用的屬性localizedDescription

do {
    try functionWhichWillThrow...
    // success ↓↓
    Statement2...
    Statement3...
    ...
} catch {
    // failure ↓↓
    print(error.localizedDescription)
}

try..catch 語法和do配合使用,當try后面的語句執(zhí)行成功后會繼續(xù)執(zhí)行do代碼塊后面的語句,如果失敗了會執(zhí)行catch中的代碼塊疏橄,該代碼塊中會攜帶一個名為error的參數(shù)。你也可以重命名該參數(shù),如下例:

do {
    try fucntion...
} catch let err {
    print(err.localizedDescription)
}

1. Throw

Swift的錯誤一般通過throw拋出異常略就,這樣使得代碼更加緊湊捎迫。

1.1 do...catch

do {
    let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers)
    print(json)
} catch {
    print(error)
}

在OC中一般使用返回值或傳入Error地址將錯誤返回,但Swfit的Error只是協(xié)議表牢,故只有遵循該協(xié)議才能使用原OC的傳遞方式窄绒。

注意:OC Api在Swift中大部分都變更為了throw的方式,但仍有部分保留該用法崔兴,例如C Api彰导,你仍可以這么做。例如這樣:

func getJson(data: Data, error: inout Error?) {
    do {
        try JSONSerialization.jsonObject(with: data, options: .mutableContainers)
    } catch let err {
        error = err
    }
}

var error: Error?
getJson(data: Data(), error: &error)
print(error)

通過inout對傳入的error進行賦值恼布。

1.2 函數(shù)拋出異常

如果你需要拋出異常螺戳,那么你需要在函數(shù)返回值之前添加throws關(guān)鍵字。

func getJson(data: Data) throws -> Any {
    return try JSONSerialization.jsonObject(with: data, options: .mutableContainers)
}

對于有異痴酃可拋出的函數(shù)來說,可以直接傳遞其異常盖腿,也可以手動創(chuàng)建異常爽待,如下:

func getJson(data: Data) throws -> Any {
    if data.count == 0 {
        throw NSError.init(domain: "", code: 0, userInfo: nil)
        // throw NSError.init(domain: "", code: 0, userInfo: nil) as Error
    }
    return data
}

1.3 重寫throw函數(shù)

throw函數(shù)的重寫和普通函數(shù)基本一樣。

class Paper {
    func getJson(data: Data) throws -> Any {
        if data.count == 0 {
            throw NSError.init(domain: "", code: 0, userInfo: nil)
        }
        return data
    }
}

class Book: Paper {
    override func getJson(data: Data) throws -> Any {
        return try super.getJson(data: data)
    }
}

配合閉包返回值翩腐,函數(shù)返回值等鸟款,你可以有各種各樣的throw用法。

2. Try

try和有異常需要拋出的函數(shù)搭配使用茂卦,用法和as相同:

try 一般和do...catch配合使用何什,關(guān)鍵字后面緊跟可能會拋出異常的函數(shù),如果成功則繼續(xù)支撐do代碼塊后面的語句等龙,失敗則執(zhí)行catch代碼塊处渣。
try? 可以在任何函數(shù)的上下文中使用伶贰,沒有失敗情況,要么成功罐栈,要么返回nil黍衙,即失敗返回nil,一般用于不關(guān)心錯誤的情況荠诬。
try! 如果確保try函數(shù)一定會返回期望值琅翻,添加!用于強制解包,和as!同理柑贞。
let p = Paper()
let a = try? p.getJson(data: Data())  // Any?

let b = try! p.getJson(data: Data())  // Any
let c = a as! Any // Any

如果傳入的data是有效值方椎,那么a、b钧嘶、c是完全相同的辩尊,try! = try? + as!,否則使用!會crash。

3. Error

由于Swift的Error是一個協(xié)議康辑,我們并不能直接創(chuàng)建Error摄欲。

上例中也只是通過NSError利用as橋接為Error類型,當我們需要使用的時候一般需要創(chuàng)建一個類型去實現(xiàn)Error協(xié)議疮薇。

enum MyError: Error {
    case network
    case jsonSerialization
    case server
}

do {
    let _ = try getJson(data: data)
} catch let error as MyError {
    switch error {
    case .jsonSerialization:
        print("json 序列化失敗")
    case .network: 
        print("網(wǎng)絡(luò)錯誤")
    case .server:
        print("服務(wù)器錯誤")
    default:
    print("未知錯誤")
    }
} catch {

}

catchelseif 分支一樣胸墙,可以添加多個,用于判斷error類型或者重命名error按咒。

localizedDescription默認是The operation couldn’t be completed.,故我們在這里重新定義該屬性的內(nèi)容迟隅。

enum MyError: Error {
    case network
    case jsonSerialization
    case server
    case unkown
    
    var localizedDescription: String {
        switch self {
        case .jsonSerialization:
            return "json 序列化失敗"
        case .network:
            return "網(wǎng)絡(luò)錯誤"
        case .server:
            return "服務(wù)器錯誤"
        default:
            return "未知錯誤"
        }
    }
}

Error不限于enum,struct,class,并且可以根據(jù)自己的需要添加任意屬性励七,比NSError靈活許多智袭。

4. fatalError

fatalError函數(shù)用于拋出異常,并且攜帶一段信息掠抬,該函數(shù)調(diào)用后一般是crash吼野。

可用于截斷當前上下文的編譯器限制,例如一定要有返回值的場景两波,添加fatalError及時后面沒有返回值瞳步,也能正常編譯。

func eat(food: String) -> String {
    if food == "Apple" {
        return "eat an apple"
    } else if food == "Banana" {
        return "eat a banana"
    }

 fatalError("不許吃其他水果")
}

eat(food: "Apple") // "eat an apple"
eat(food: "Egg") // Thread 1: Fatal error: 不許吃其他水果

當我們預(yù)料到某些情況一定會發(fā)生錯誤的時候腰奋,但實際使用上一定不會那么使用時单起,可以通過該方式防止編譯器對語法進行檢查,以免我們?nèi)ヌ砑右恍o效代碼去滿足語法劣坊。

或者我們不允許某些我們不想看到的使用場景出現(xiàn)嘀倒,則可以使用該函數(shù),例如:

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

這是系統(tǒng)的默認實現(xiàn),我們必須在這里進行初始化测蘑,或者返回nil灌危,如果不返回,要么這里需要將所有屬性初始化完畢帮寻,要么fatalError直接拋出異常乍狐。而這里則選擇的是fatalError,其實return nil也可以避免初始化固逗。

 class View: UIView {
    override class var layerClass: AnyClass { 
        return AVCaptureVideoPreviewLayer.self 
    }

    var previewLayer: AVCaptureVideoPreviewLayer {
        if let layer = self.layer as? AVCaptureVideoPreviewLayer {
            return layer
        } else {
            fatalError("error")
        }
    }
}

這個例子layer一定是AVCaptureVideoPreviewLayer類型浅蚪,即if let語法一定成立,fatalError被用來打斷編譯器檢查烫罩,其實直接使用as!也一樣惜傲。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市贝攒,隨后出現(xiàn)的幾起案子盗誊,更是在濱河造成了極大的恐慌,老刑警劉巖隘弊,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件哈踱,死亡現(xiàn)場離奇詭異,居然都是意外死亡梨熙,警方通過查閱死者的電腦和手機开镣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來咽扇,“玉大人邪财,你說我怎么就攤上這事≈视” “怎么了树埠?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長嘶伟。 經(jīng)常有香客問我怎憋,道長,這世上最難降的妖魔是什么奋早? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任盛霎,我火速辦了婚禮,結(jié)果婚禮上耽装,老公的妹妹穿的比我還像新娘。我一直安慰自己期揪,他們只是感情好掉奄,可當我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般姓建。 火紅的嫁衣襯著肌膚如雪诞仓。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天速兔,我揣著相機與錄音墅拭,去河邊找鬼。 笑死涣狗,一個胖子當著我的面吹牛谍婉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播镀钓,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼穗熬,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了丁溅?” 一聲冷哼從身側(cè)響起唤蔗,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎窟赏,沒想到半個月后妓柜,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡涯穷,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年棍掐,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片求豫。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡塌衰,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蝠嘉,到底是詐尸還是另有隱情最疆,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布蚤告,位于F島的核電站努酸,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏杜恰。R本人自食惡果不足惜获诈,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望心褐。 院中可真熱鬧舔涎,春花似錦、人聲如沸逗爹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至挟冠,卻和暖如春于购,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背知染。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工肋僧, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人控淡。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓嫌吠,卻偏偏與公主長得像,于是被迫代替她去往敵國和親逸寓。 傳聞我的和親對象是個殘疾皇子居兆,可洞房花燭夜當晚...
    茶點故事閱讀 44,713評論 2 354