日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

Swift 小技巧(三):如何用 Swift 思維設(shè)計網(wǎng)絡(luò)請求 | I'm TualatriX

 quasiceo 2015-02-19

近來在用 Swift 開發(fā) App 的過程中,最大的心得就是:我開始漸漸用「Swift 思維」來思考了。回顧剛開始我用 Swift 時,只是套用它的語法而已,腦子里依然是 Objective-C 思維。

這段時間,隨著對 Swift 基本特性的掌握,我開始有意識地學習并嘗試一些 Swift 才有的特性,此謂「Swift 思維」。Swift 有很多專有(Objective-C 沒有的)的模式,今天我就從一個很簡單的例子講起,那就是:

如何用 Swift 思維設(shè)計網(wǎng)絡(luò)請求。

做過網(wǎng)絡(luò)類應用的同學應該都知道,我們做一個網(wǎng)絡(luò)請求時,通常會有兩個結(jié)果:一個是失敗,返回錯誤,一個是成功,返回結(jié)果。當然途中還會有更復雜的情況,比如:1、網(wǎng)絡(luò)請求本身的失?。ū热缇W(wǎng)絡(luò)超時);2、API 端返回的內(nèi)部結(jié)果型失?。ū热缑艽a不正確)。這里我們就不細分了。

在傳統(tǒng)的 Objective-C 的項目里,有幾種處理這種異常的情況,主要是:

1、直接判斷 NSError 

NSError *error = nil;

id result = [API doSomething:&error];

if (error != nil) {
   NSLog("Oh Error!")
}

這種處理太直白,一般會阻塞當前的線程,因而不推薦。一般用的比較多的是下面兩種:

2、通過 success,failture 的 block 來處理

[API doSomethingWithSuccess:^(id result) {

    NSLog(@"Seems good")

} failure:^(NSError *error) {

    NSLog(@"Oh Error!")

}];

這種就相對好點了,通過 Block 及內(nèi)部實現(xiàn),可以做到不阻塞當前線程,在有結(jié)果的時候再進行處理。在對應的 Block 處理對應的情況:成功 or 失敗。 不過這個設(shè)計依然還有一點缺陷,因為它對結(jié)果的處理分散在不同的 Block,如果我需要統(tǒng)一處理無論成功或失敗的情況,那么需要分別調(diào)用,不是太直觀了。所以,我們還有第三種模式。

3、通過統(tǒng)一的 completionHander 的 block 來處理

[API doSomethingWithCompletionHandler:^(id result, NSError *error) {
    if result != nil {
        NSLog(@"Seems good")
    }

    if error != nil {
        NSLog(@"Oh Error!")
    }
}];

這種通過 CompletionHandler 來統(tǒng)一作成功結(jié)果和錯誤失敗的處理應該是現(xiàn)在設(shè)計的首先,包括系統(tǒng)自己的 API 也是這樣設(shè)計的。特別適合在一個 Block 里就把所有情況處理掉的需求。

Swift 式網(wǎng)絡(luò)請求處理

簡單列舉了三種 Objective-C 下常見的網(wǎng)絡(luò)請求類處理方式,看起來還不錯,那么 Swift 模式是什么樣的,能做好更好嗎?我覺得是的。

Swift 里有著非常棒的 enum 機制,所有的枚舉情況不但可以是任何類型,而且可以是不一樣的類型。這意味著,我們在 Swift 里可以包裝一種結(jié)果型 enum,比如:

enum Result {
    case Error(NSError)
    case Value(JSON)

    init(_ e: NSError, _ v: JSON) {
        if let ex = e {
            self = Result.Error(ex)
        } else {
            self = Result.Value(v)
        }
    }
}

這段是我真實世界的代碼,用在了我的微博客戶端里。

代碼很簡單,我定義了一個名為「Result」的 enum 對象,它會包裝兩種情況,一種是 Value,在網(wǎng)絡(luò)請求成功時,它就是一個 JSON 值;第二種時 Error,是一個 NSError 值,在網(wǎng)絡(luò)請求失敗時,包含著具體的錯誤信息。

這樣,就成功地把一個網(wǎng)絡(luò)請求下的可能的兩種情況包裝在了一個 Result 對象里,這個對象,要么是成功的結(jié)果,要么就是失敗的錯誤,永遠不會有同時有結(jié)果和錯誤。于是,我們的網(wǎng)絡(luò)請求處理代碼可以更為簡單的設(shè)計成這樣:

API.doSomethingWithCompletionHandler({ (result) -> Void in
    switch (result) {
    case let .Error(e):
        NSLog("Oh Error!")
    case let .Value(json):
        NSLog("Seems good")
    }
})

看起來似乎和前面 Objective-C 的第二種模式一樣?似乎又像第三種?估且稱之為混合模式吧。讓我來簡單說說這種模式有什么好處:

首先,我們通過 Switch 條件判斷這種非此即彼的模式,我們可以減少很多錯誤的發(fā)生,保證條件分支判斷不會出問題;其次,我們依然只是在一個 Closure (這里換成 Swift 術(shù)語,而不是 Objective-C 的 Block)處理我們的一個請求結(jié)果 result,因而可以在前前后后做些其他對結(jié)果的統(tǒng)一處理,保證我們邏輯的統(tǒng)一性。

這就是我所認為的 Swift 這種模式的好處了。

通過這種模式改造我的項目后,我覺得代碼變得更整潔、邏輯清晰,也不會有遺失的錯誤處理情況。當然我做采用的還只是簡化版的 Swift 模式網(wǎng)絡(luò)處理,更為強大的例子大家可以參考 swiftz 項目的 Result 對象,它使用了 Swift 的 Generic 特性,從而使其可以包裝任意值(不僅僅是 JSON),從而大大增強了擴展性:https://github.com/typelift/swiftz/blob/master/swiftz_core/swiftz_core/Result.swift#L12

我依然還在用 Swift 思維改造項目的過程中,目前這種模式應該還是有改進余地的,希望能和大家做更多有關(guān)這個的討論與交流。

Tag: Swift.

<推廣> Manico 是一個專門為 OS X 高效率人士設(shè)計的 App 啟動與切換工具,使用它將加倍電腦日常使用的效率。

You can leave a comment.

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多