Swift源碼(Alamofire)學(xué)習(xí)之錯誤處理篇(AFError)

從AFError看Swift枚舉用法

女兒惹她媽媽生氣了,我讓她去道歉。
“知錯就改,快去找你媽,認錯?!蔽掖叽偎?br> 小家伙猶豫了半天,終于走進了廚房,對她媽說道:
“媽媽,請問你是劉亦菲嗎?”
妻子很疑惑:“不是啊。”
“哦,對不起,我認錯了?!?/p>


枚舉為一組相關(guān)值定義了一個公共類型,使您能夠在代碼中以類型安全的方式處理這些值。(Apple官方文檔的定義)


舉個??

enum ADayWork {
case watchNews
case listenMusic
case napp
case chat
case code
}

let now = ADayWork.napp

switch now {
case .watchNews:
    print("我正在刷頭條")
case .listenMusic:
    print("哼哼哈嘿,快使用雙節(jié)棍")
case .napp:
    print("我剛干啥了又")
case .chat:
    print("這個妹子怎么不回我啊")
case .code:
    print("這需求,我擦,找找網(wǎng)上有沒有類似的輪子")
}

上面基本是我們通常的用法,定義一組具有相關(guān)性的值,使用的時候進行相應(yīng)的處理。但是,如果只是這樣使用,那真是浪費了Swift把它提升為一等公民的良苦用心了。

在Swift中你可以定義Swift枚舉以存儲任何給定類型的關(guān)聯(lián)值,并且如果需要,每種枚舉情況的值類型可以不同。

緊隨上面的??

enum ADayWork {
        enum Mood:String{
            case happy = "哈哈哈"
            case bored = "無聊"
            case anger = "ca"
        }
        
        
        case napp(minutes:Int)
        case chat(friendName:String)
        case listenMusic(musicName:String,singer:String,player:String)
        case code(mood:Mood)
        ///函數(shù)也是一等公民了,現(xiàn)在也可以當做參數(shù)和返回值了
        case watchNews(pagesName:String,feeling:((Mood) -> ()))
    
    }
    let napp = ADayWork.napp(minutes:30)
    
     let chat = ADayWork.chat(friendName:"劉亦菲")
    
    let listenMusic = ADayWork.listenMusic(musicName: "雙節(jié)棍", singer: "周杰倫", player: "QQ音樂")     
    
    let code = ADayWork.code(mood:.happy)
    
    let watchNews = ADayWork.watchNews(pagesName: "今日頭條") { (mood) in
        print("\(mood.rawValue)")
    }
    let arr:[ADayWork] = [napp,chat,listenMusic,code,watchNews]
    
    for doWhat in arr {
        switch doWhat {
        case .napp(let minute):
            print("我剛發(fā)呆了\(minute)分鐘")
        case .chat(let friendName):
            print("我在和\(friendName)聊騷")
        case .listenMusic(let musicName,let singer,let player):
            print("我正在用\(player) 聽 \(singer) 唱的 \(musicName) 哎呦不錯哦")
        case .code(let mood):
            print("這需求,我擦,找找網(wǎng)上有沒有類似的輪子,找到了,\(mood)")
        case .watchNews(let pageNames,let feeling):
            print("我在用\(pageNames)刷新聞")
            feeling(.happy)
        }
    }
    
    
輸出結(jié)果:
我剛發(fā)呆了30分鐘
我在和劉亦菲聊騷
我正在用QQ音樂 聽 周杰倫 唱的 雙節(jié)棍 哎呦不錯哦
這需求,我擦,找找網(wǎng)上有沒有類似的輪子,找到了,happy
今日頭條
感覺很happy

靈兒我來啦

image

你可以選擇存儲任意類型的關(guān)聯(lián)值,這就大大拓展了枚舉的應(yīng)用場景了。

當然這里我只是列舉了下枚舉關(guān)聯(lián)值的基本用法,想要詳細了解枚舉的話,可以參考這篇文章


AFError中對枚舉的用法

錯誤類型

AFError中將錯誤定義成了五個大類型

image
  • invalidURL-無效的URL
    關(guān)聯(lián)值類型是URLConvertible,這是一個協(xié)議,定義了方法func asURL() throws -> URL,協(xié)議下面有幾個實現(xiàn)
    image

    通過String,URL,URLComponents的實現(xiàn)可以看出這個協(xié)議的作用是可以轉(zhuǎn)換任意類型為URL類型,從而方便使用。而關(guān)聯(lián)這個類型的值目的是為了當URL無效的時候,可以通過關(guān)聯(lián)值獲取到,然后進行打印等操作。

比如

    ///聲明結(jié)構(gòu)體,或者其他任意類型都行
    struct Dog {
        var dogName:String = ""
    }
    ///只要實現(xiàn)了協(xié)議URLConvertible的方法
    extension Dog:URLConvertible{
        public func asURL() throws -> URL {
            guard let url = URL(string: self.dogName) else
            {
             ///失敗的話則拋出異常,并且將urlString關(guān)聯(lián)在枚舉值中
                throw AFError.invalidURL(url: self.dogName)
            }
         return url
        }
    }   
    ///使用 - 這里如果失敗的話就會捕獲到invalidURL這個異常,并且可以獲取到錯誤的url
    let url = try Dog().asURL()

其實這里可以看出協(xié)議的好處了,特別是 Swift 支持拓展協(xié)議,任意的類型,只要實現(xiàn)了相應(yīng)的協(xié)議,就擁有了相應(yīng)的功能。后面會再分析下 Swift 面向協(xié)議的寫法。

這里推薦一本書 - Swift面向協(xié)議編程

image

另外兩本書我還沒看,不過感覺應(yīng)該也還不錯。千萬不要找那些什么多少天精通,什么從基礎(chǔ)到高深。除非你是小白。

看來之后你就會發(fā)現(xiàn),還要啥對象啊。自己一個人不好玩么?


  • parameterEncodingFailed-參數(shù)編碼失敗

    關(guān)聯(lián)值類型是ParameterEncodingFailureReason,這又是一個枚舉,列舉了可能會導(dǎo)致參數(shù)編碼失敗的原因。

    1. missingURL - urlRequest.url不存在
    2. jsonEncodingFailed(error: Error) - 參數(shù)編碼成JSON失敗
    3. propertyListEncodingFailed(error: Error) 參數(shù)編碼成propertyList失敗
  • multipartEncodingFailed-參數(shù)編碼失敗
    多部分編碼錯誤一般發(fā)生在上傳或下載請求中對數(shù)據(jù)的處理過程中,這里邊最重要的是對上傳數(shù)據(jù)的處理過程

  • responseValidationFailed-參數(shù)編碼失敗
    Alamofire不管請求是否成功,都會返回response。它提供了驗證ContentType和StatusCode的功能

  • responseSerializationFailed-參數(shù)編碼失敗
    Alamofire支持把服務(wù)器的response序列化的時候發(fā)生的錯誤

由于我們這里主要關(guān)注AFError對于枚舉的使用,所以這些錯誤類型我就不一一翻譯了。

錯誤快速定位判斷

在源碼中我們可以發(fā)現(xiàn)

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

    /// Returns whether the AFError is a parameter encoding error. When `true`, the `underlyingError` property will
    /// contain the associated value.
    public var isParameterEncodingError: Bool {
        if case .parameterEncodingFailed = self { return true }
        return false
    }

這里通過對枚舉拓展了計算屬性,來直接對錯誤類型進行if判斷,不用在switch一個一個判斷了。

let err = AFError.invalidURL(url: Dog.init(dogName:"123"))
if err. isInvalidURLError {
    print("我只關(guān)注這個錯誤是不是url錯了,是啥錯誤類型我不關(guān)心")
}

一些比較方便的計算屬性

extension AFError {

/// The `URL` associated with the error.
public var url: URL? {
    switch self {
    case .multipartEncodingFailed(let reason):
        return reason.url
    default:
        return nil
    }
}

/// The `Error` returned by a system framework associated with a `.parameterEncodingFailed`,
/// `.multipartEncodingFailed` or `.responseSerializationFailed` error.
public var underlyingError: Error? {
    switch self {
    case .parameterEncodingFailed(let reason):
        return reason.underlyingError
    case .multipartEncodingFailed(let reason):
        return reason.underlyingError
    case .responseSerializationFailed(let reason):
        return reason.underlyingError
    default:
        return nil
    }
}

當我們不想switch一個一個判斷錯誤類型,并且我們知道這個錯誤是什么類型的時候,我們就可以直接.屬性,來直接定位到精準的錯誤信息

let err = AFError.invalidURL(url: Dog.init(dogName:"123"))   
print("我知道這個錯誤是url錯誤了,現(xiàn)在他的錯誤的url是\(err. url)")

錯誤描述

通過實現(xiàn)LocalizedError這個協(xié)議并且實現(xiàn)它的計算屬性errorDescription,針對不同的錯誤來分別進行錯誤信息的描述。

這里的代碼結(jié)構(gòu)十分清晰,針對每個枚舉的錯誤定義localizedDescription計算屬性并返回錯誤描述。大家可以仔細品味下。

最終

感覺挺啰嗦,但是好像又沒真正的講解好,大家如果有什么意見的話可以提出來,一起學(xué)習(xí),共同進步。

不過真正寫出來了感覺對枚舉的值類型應(yīng)用的確加深了一層理解。希望大家以后也可以不僅是看,也要寫。

聯(lián)系方式

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

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