Swift Error 的介紹和使用

同步我的掘金MeR

??鶸學(xué)python看到錯(cuò)誤處理這一章的時(shí)候,就想對(duì)比著swift來研究一下茫陆。
??本文前面是Error蘋果文檔的介紹,然后對(duì)Alamofire中的使用作簡(jiǎn)單介紹作為實(shí)踐擎析;后面還有關(guān)于fatalError和高級(jí)語(yǔ)言錯(cuò)誤處理機(jī)制的理解


Error蘋果文檔

Swift中的Error長(zhǎng)這個(gè)樣子

public protocol Error {
}

extension Error {
}

extension Error where Self.RawValue : SignedInteger {
}

extension Error where Self.RawValue : UnsignedInteger {
}

蘋果文檔對(duì)Error的介紹

A type representing an error value that can be thrown. Any type that declares conformance to the Error protocol can be used to represent an error in Swift’s error handling system. Because the Error protocol has no requirements of its own, you can declare conformance on any custom type you create.

??從介紹上可以看出遵守這個(gè)Error協(xié)議簿盅,就可以將錯(cuò)誤拋出和捕獲,而且任何自定義的類型都可以遵守此Error協(xié)議揍魂。
??文檔中舉了兩個(gè)例子桨醋,第一個(gè)是自定義枚舉遵守Error來對(duì)Error進(jìn)行分類,下面我們著重看下蘋果爸爸給出的第二個(gè)例子:用一個(gè)遵守Error協(xié)議的結(jié)構(gòu)體來獲取更多的錯(cuò)誤信息现斋。

struct XMLParsingError: Error {
    enum ErrorKind {
        case invalidCharacter
        case mismatchedTag
        case internalError
    }

    let line: Int
    let column: Int
    let kind: ErrorKind
}

func parse(_ source: String) throws -> XMLDoc {
    // ...
    throw XMLParsingError(line: 19, column: 5, kind: .mismatchedTag)
    // ...
}

例子中創(chuàng)建了一個(gè)遵守Error協(xié)議的結(jié)構(gòu)體 XMLParsingError喜最,帶有三個(gè)屬性來記錄解析XML文件時(shí)出錯(cuò)的錯(cuò)誤類型和行列信息。這樣在執(zhí)行parse方法的時(shí)候庄蹋,就可以捕獲到可能的出現(xiàn)的錯(cuò)誤信息

do {
    let xmlDoc = try parse(myXMLData)
} catch let e as XMLParsingError {
    print("Parsing error: \(e.kind) [\(e.line):\(e.column)]")
} catch {
    print("Other error: \(error)")
}
// Prints "Parsing error: mismatchedTag [19:5]"

Alamofire中的錯(cuò)誤示例

??刻意看了下Alamofire中的錯(cuò)誤處理瞬内,它用單獨(dú)的一個(gè)文件AFError來管理使用中的錯(cuò)誤,其中自定義了枚舉

public enum AFError: Error {
                                encoding process.
    public enum ParameterEncodingFailureReason {
        case missingURL
        case jsonEncodingFailed(error: Error)
        case propertyListEncodingFailed(error: Error)
    }

    
    public enum MultipartEncodingFailureReason {
        case bodyPartURLInvalid(url: URL)
        case bodyPartFilenameInvalid(in: URL)
        case bodyPartFileNotReachable(at: URL)
        case bodyPartFileNotReachableWithError(atURL: URL, error: Error)
        case bodyPartFileIsDirectory(at: URL)
        case bodyPartFileSizeNotAvailable(at: URL)
        case bodyPartFileSizeQueryFailedWithError(forURL: URL, error: Error)
        case bodyPartInputStreamCreationFailed(for: URL)

        case outputStreamCreationFailed(for: URL)
        case outputStreamFileAlreadyExists(at: URL)
        case outputStreamURLInvalid(url: URL)
        case outputStreamWriteFailed(error: Error)

        case inputStreamReadFailed(error: Error)
    }

    
    public enum ResponseValidationFailureReason {
        case dataFileNil
        case dataFileReadFailed(at: URL)
        case missingContentType(acceptableContentTypes: [String])
        case unacceptableContentType(acceptableContentTypes: [String], responseContentType: String)
        case unacceptableStatusCode(code: Int)
    }

    
    public enum ResponseSerializationFailureReason {
        case inputDataNil
        case inputDataNilOrZeroLength
        case inputFileNil
        case inputFileReadFailed(at: URL)
        case stringSerializationFailed(encoding: String.Encoding)
        case jsonSerializationFailed(error: Error)
        case propertyListSerializationFailed(error: Error)
    }

    case invalidURL(url: URLConvertible)
    case parameterEncodingFailed(reason: ParameterEncodingFailureReason)
    case multipartEncodingFailed(reason: MultipartEncodingFailureReason)
    case responseValidationFailed(reason: ResponseValidationFailureReason)
    case responseSerializationFailed(reason: ResponseSerializationFailureReason)
}

以此將使用中出現(xiàn)的錯(cuò)誤進(jìn)行分類限书。
??不僅如此虫蝶,作者還將AFError進(jìn)行了擴(kuò)展,增加部分判斷的方法倦西,比如判斷是否是無(wú)效的URL:

// MARK: - Error Booleans

extension AFError {
    /// Returns whether the AFError is an invalid URL error.
    public var isInvalidURLError: Bool {
        if case .invalidURL = self { return true }
        return false
    }
}

同時(shí)拓展中也遵守了LocalizedError協(xié)議來重寫errorDescription屬性能真,并且對(duì)已經(jīng)分類enum的自定義錯(cuò)誤類型進(jìn)行拓展重寫了屬性localizedDescription,這樣就構(gòu)成了項(xiàng)目中完整的錯(cuò)誤處理機(jī)制。比如在Alamofire編碼解析方法方法encode中扰柠,有這么一段代碼

do {
            let data = try JSONSerialization.data(withJSONObject: jsonObject, options: options)

            if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil {
                urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
            }

            urlRequest.httpBody = data
        } catch {
            throw AFError.parameterEncodingFailed(reason: .jsonEncodingFailed(error: error))
        }

其中就是對(duì)于JSON序列化時(shí)舟陆,通過 do { try } catch 的方式來捕獲錯(cuò)誤,如果捕獲到耻矮,將拋出已經(jīng)自定義好的 AFError.parameterEncodingFailed(reason: .jsonEncodingFailed(error: error)) 類型錯(cuò)誤。


fatalError

還有一個(gè)錯(cuò)誤相關(guān)的是 fatalError, 蘋果對(duì)其的描述:

Unconditionally prints a given message and stops execution.

定義:

/// - Parameters:
///   - message: The string to print. The default is an empty string.
///   - file: The file name to print with `message`. The default is the file
///     where `fatalError(_:file:line:)` is called.
///   - line: The line number to print along with `message`. The default is the
///     line number where `fatalError(_:file:line:)` is called.
public func fatalError(_ message: @autoclosure () -> String = default, file: StaticString = #file, line: UInt = #line) -> Never

這個(gè)我們估計(jì)最常見的地方就是在 init(coder: NSCoder) 中看到它忆谓,它的作用如蘋果描述的裆装,無(wú)條件的打印出給定的信息同時(shí)終止程序。按照喵神的描述倡缠,fatalError的存在意義是:

<font size=3>在調(diào)試時(shí)我們可以使用斷言來排除類似這樣的問題哨免,但是斷言只會(huì)在 Debug 環(huán)境中有效,而在 Release 編譯中所有的斷言都將被禁用昙沦。在遇到確實(shí)因?yàn)檩斎氲腻e(cuò)誤無(wú)法使程序繼續(xù)運(yùn)行的時(shí)候琢唾,我們一般考慮以產(chǎn)生致命錯(cuò)誤 fatalError 的方式來終止程序。</font>

而實(shí)際開發(fā)中喵神給出兩個(gè)使用的場(chǎng)景:

  1. 父類中的某些方法盾饮,不想讓別人調(diào)用采桃,可以在方法中加上fatalError懒熙,這樣子類如果想到用必須重寫
  2. 對(duì)于其他一切我們不希望別人隨意調(diào)用,但是又不得不去實(shí)現(xiàn)的方法普办,我們都應(yīng)該使用 fatalError 來避免任何可能的誤會(huì)工扎。

關(guān)于第二點(diǎn)就是我們常見到的在重寫UIView init(frame:) 時(shí),Xcode會(huì)提示需要顯示重寫 init(coder: NSCoder)衔蹲,并且給出默認(rèn)實(shí)現(xiàn)的原因:

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

UIView遵守了協(xié)議 NSCoding肢娘,此協(xié)議要求實(shí)現(xiàn) init(coder: NSCoder)

public init?(coder aDecoder: NSCoder) // NS_DESIGNATED_INITIALIZER

詳細(xì)的場(chǎng)景介紹請(qǐng)看喵神的文章


關(guān)于錯(cuò)誤處理機(jī)制

??鶸之前也想過錯(cuò)誤處理機(jī)制的意義舆驶,返回一個(gè)狀態(tài)碼不就好了橱健。比如我們打開一個(gè)文件,成功了返回一個(gè)整數(shù)的描述符沙廉,錯(cuò)誤了就返回-1;或者我們請(qǐng)求聯(lián)網(wǎng)拘荡,如果參數(shù)有問題,會(huì)和后臺(tái)約定一個(gè)數(shù)字作為錯(cuò)誤碼蓝仲,也都很好俱病。然而只是單純的用錯(cuò)誤碼會(huì)面臨兩個(gè)問題:

  1. 用錯(cuò)誤碼來表示是否出錯(cuò)十分不便,因?yàn)楹瘮?shù)本身應(yīng)該返回的正常結(jié)果和錯(cuò)誤碼混在一起袱结,造成調(diào)用者必須用大量的代碼來判斷是否出錯(cuò)亮隙。
  2. 一旦出錯(cuò),還要一級(jí)一級(jí)上報(bào)垢夹,直到某個(gè)函數(shù)可以處理該錯(cuò)誤(比如溢吻,給用戶輸出一個(gè)錯(cuò)誤信息)。

高級(jí)語(yǔ)言的錯(cuò)誤處理機(jī)制就解決了這些問題果元。

喵神FATALERROR
蘋果文檔Error
廖雪峰python

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末促王,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子而晒,更是在濱河造成了極大的恐慌蝇狼,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件倡怎,死亡現(xiàn)場(chǎng)離奇詭異迅耘,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)监署,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門颤专,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人钠乏,你說我怎么就攤上這事栖秕。” “怎么了晓避?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵簇捍,是天一觀的道長(zhǎng)只壳。 經(jīng)常有香客問我,道長(zhǎng)垦写,這世上最難降的妖魔是什么吕世? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮梯投,結(jié)果婚禮上命辖,老公的妹妹穿的比我還像新娘。我一直安慰自己分蓖,他們只是感情好尔艇,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著么鹤,像睡著了一般终娃。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蒸甜,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天棠耕,我揣著相機(jī)與錄音,去河邊找鬼柠新。 笑死窍荧,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的恨憎。 我是一名探鬼主播蕊退,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼憔恳!你這毒婦竟也來了瓤荔?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤钥组,失蹤者是張志新(化名)和其女友劉穎输硝,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體程梦,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡腔丧,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了作烟。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡砾医,死狀恐怖拿撩,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情如蚜,我是刑警寧澤压恒,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布影暴,位于F島的核電站,受9級(jí)特大地震影響探赫,放射性物質(zhì)發(fā)生泄漏型宙。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一伦吠、第九天 我趴在偏房一處隱蔽的房頂上張望妆兑。 院中可真熱鬧,春花似錦毛仪、人聲如沸搁嗓。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)腺逛。三九已至,卻和暖如春衡怀,著一層夾襖步出監(jiān)牢的瞬間棍矛,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工抛杨, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留够委,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓蝶桶,卻偏偏與公主長(zhǎng)得像慨绳,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子真竖,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • error code(錯(cuò)誤代碼)=0是操作成功完成脐雪。error code(錯(cuò)誤代碼)=1是功能錯(cuò)誤。error c...
    Heikki_閱讀 3,379評(píng)論 1 9
  • error code(錯(cuò)誤代碼)=2000是無(wú)效的像素格式恢共。error code(錯(cuò)誤代碼)=2001是指定的驅(qū)動(dòng)...
    Heikki_閱讀 1,798評(píng)論 0 4
  • 原文: Alamofire 4.0 Migration Guide作者: cnoon譯者: kemchenj 譯者...
    kemchenj閱讀 2,963評(píng)論 4 12
  • 初中時(shí),我有一個(gè)最好的朋友透硝。我們一起上課下課狰闪,聊八卦。我去她家過夜濒生,她來我家吃飯埋泵。媽媽每次問,她最近怎樣了,好久沒...
    黃馬立閱讀 189評(píng)論 0 0
  • 圣誕節(jié)晚上吃飯時(shí)我問K丽声,2017的目標(biāo)有哪些礁蔗。他所說的其中有一條是:通過HSK四級(jí)。今日又在微信群里收到母上大人布...
    天漫一閱讀 794評(píng)論 0 2