網絡層的參考姿勢

網絡是任何一個系統/平臺的基礎功能,在iOS上也同樣是這樣的.從NSURLConnectionNSURLSession,從ASIHttpRequest到目前最主流的AFNetworking.

事實上,一個項目中通常會有一個更高層次的封裝.可以是自行基于NSURLConnection進行封裝,也可以基于AFNetworking或者Alamofire.

這里提供一個參考的姿勢:ZCNetworking

結構

主要提供了3層

  1. 網絡常用操作的抽象層:ZCNetworking,這里是基于AFNetworking
  2. 針對項目的具體操作Runner層:ZCApiRunner;提供大量的功能,配置以簡化項目中的實際使用.
  3. Actions:普通/上傳/下載操作的封裝;包括參數/url等,也提供了一些便利操作,比如好用的log.

抽象層

這是比較重要的一層,將網絡操作和具體實現隔離開來.僅僅暴露出一些task.

有了這一層,那么替換基礎庫就成為可能.ZCNetworking是基于AFNetworking,或許有一天會修改成其他的networking或者是直接使用NSURLSession呢?如果改動,只需要改動這一層即可,而整個項目不會受到任何影響.

這一層本身只提供幾個基礎方法:

  1. 數據獲取: sendRequest
  2. 上傳: uploadTask
  3. 下載:downloadFile;還包含了一個下載圖片的方法
  4. 一些基礎的操作方法,比如cookie等

基礎方法中也提供了2種形式,以方便配置:包含NSURLSessionConfiguration和不包含.當然不包含則是默認.

暴露的接口較少,當然完全可以根據實際需求進行擴充.不過需要確定的一點就是:接口完全和任意第三方類無關.這樣才能使得替換底層實現與上層無關.

接口的實現沒有太多要注意的.按照正常的AFNetworking使用即可.

Runner

這一層是針對于項目的具體實現,做一些公共的配置/設置.包括:

  1. 區分正式/測試服務器
  2. 公共參數的處理,例如headers,params
  3. 對于邏輯成功/失敗的處理
  4. 對于數據獲取/上傳/下載的處理
  5. 對于batch操作的處理
  6. 對于chain操作的處理
服務器區分

通常項目會有至少2個以上的服務器,正式和測試服務器.而對于服務器地址的管理,有多種方式.可以是純手工的管理;可以是參數的配置,例如做一個宏;也可以做多個target;

純手工當然不可取,太容易出錯.好吧..說的就是我..的確因為疏忽翻過這樣的錯誤.

配置本質上也是純手工,只是設立了一個總開關.但是一旦疏忽,仍然有風險.

target會不會太heavy了點?假設還有cdn呢...

于是ZCNetworking中,根據當前環境來自行決定使用的服務器:

- (void)startWithDebugDomain:(NSString *)debug releaseDomain:(NSString *)release {
    _debugDomain = debug;
    _releaseDomain = release;
}

- (NSString *)currentDomain {
    if (_forceDomain.length > 0) {
        return _forceDomain;
    }
    else {
#ifdef DEBUG
        return _debugDomain;
#else
        return _releaseDomain;
#endif
    }
}

其中還增加了一個forceDomain,可以強制使用某個環境,這樣便于調試.

公共參數

大多數項目會有這樣的需求.例如我這里會為每一個請求中加上這樣一組header:

headers[@"X-REQUESTED-WITH"] = @"1";

項目中也會需要公共參數,例如每條api需要版本號和平臺等.

ZCNetworking在Runner中提供了相應的接口:addtionalHeadersglobleParams.

邏輯判定

基礎網絡只能夠判定物理上是否成功.比如是否是http 200等.但是在很多時候,邏輯上的失敗也是失敗,應該進入failure流程,不應該進入success流程再進行判定.

例如登錄操作.用戶名密碼錯誤然后返回.此時物理上成功(http 200),但是邏輯上失敗.則應當進入失敗流程.

對于一些公共錯誤,可能會有公共的操作方式.例如token/cookie過期導致登錄失效,那么會彈出登錄UI等.

所以會有幾個操作:
codeKey/successCodes/warningCodes&&handler

codeKey則是返回字典的key

successCodes是個數組.如果返回字典的codekey字段的值滿足successCodes,則認為邏輯成功,否則邏輯失敗

warningCodes主要處理通用的錯誤,例如登錄失效.handler當然就是處理的方式了.

是否邏輯成功完全依賴successCodes,和warningCodes無關.

不過這需要服務端提供類似的邏輯才行,如果提供不了,不設置即可.將不會對返回的邏輯狀態進行處理,僅僅依賴物理狀態.

請求的操作

一共就數據請求,上傳,下載三大類.對應NSURLSessionDataTask/NSURLSessionUploadTask/NSURLSessionDownloadTask

利用之前的抽象層進行請求即可.不過請求內容已經被封裝成Action類型.包括url,params等東西.

當物理狀態返回后,根據配置對邏輯狀態進行檢查(不檢查),最終返回相應的數據.

在請求中,有log是最方便的.以前關于調試,一般就2種方式:

  1. 斷點
  2. 使用工具,例如charles.

不過斷點不太方便,涉及到變量以及作用于的問題.針對個別問題還成,針對每一個請求都調試一翻,效率較低.

charles很好用,就是有點貴...

所以如果附帶log信息的話,可能性價比較高.ZCNetworking提供了一些log信息:

  1. url和參數,以xxx.com/action?a=xx&b=xx的方式拼接,對于部分get請求可以直接用瀏覽器調用.
  2. method/header/params
  3. 對于error的log,包括物理和邏輯上的
  4. 返回值log,方便查看數據結構

log信息由action中的參數showLog來控制.

batch

不算特別常用的功能.但似乎也有點用.

例如在一個頁面中,需要調用多條api才能將數據獲取完畢,然后渲染界面.當然,這種方式顯然不太好,加入某條api出錯了呢?

在巧哥的YTKNetworking中也提供了同樣的功能.使用一個count進行計數.當請求返回,則在返回中count++.當count等于請求的個數,則執行完畢.

ZCNetworking中,通過dispatch group處理這個功能.不過該功能有2個策略.
1.batch中一旦出錯,立刻停止,返回錯誤.
2.batch中一旦出錯,繼續執行,最終返回一個字典.key為url,value為返回值.或許是object,或許是error.當然如果都成功,則返回字典.key為url,value為object.

ZCNetworking選擇的是第一種策略.當然你也可以選擇其他的策略.

chain

也不算特別常用的功能.也似乎有點用.

例如產品是必須先登錄->在獲取數據.

YTKNetworking類似于遞歸的感覺,通過next index計數,在請求完成后繼續執行next,直到請求隊列完畢.

ZCNetworking中使用semaphore來處理chain,不過遇上了一個坑.

信號量是一個簡單的思路.類似于餐廳座位.有座位了就進入,沒座位了就等待.進入后,座位少一張,出來后座位多一張,下個人才能進.

然而,在創建了一個信號量以后,使用AFHTTPSessionManager發送get請求居然沒有反應!而使用NSURLSession卻可以請求.

查找一番后,問題出現在了兩個main thread死鎖的地方.也就是信號量和AFHTTPSessionManager的默認complate queue.這個時候,手動設置complate queue即可:

manager.completionQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

返回值依然是一個字典,key為url.

當然會出現url相同的情況,這個時候key如何處理可以多斟酌一番,加上index?

more

需求的功能當然還可以有更多,例如巧哥提供了緩存,返回值驗證,斷點續傳等
有必要的話完全可以繼續擴展

Action(Model)

網絡庫的核心思路是把每一個請求封裝成對象.所以每一個請求對應一個Action

請求有3種,action當然也就有3個.

  • ZCApiAction
  • ZCApiUploadAction
  • ZCApiDownloadAction

后2種繼承自第一種.action中主要包含api的請求相關信息,例如url,params等.也包含一些api的控制信息,例如log開關.最后提供了2個回調,實現"插件機制":

typedef void (^ZCActionComplation) (BOOL isSuccess);
typedef void (^ZCVoidBlock) (void);

@property (nonatomic, copy)   ZCVoidBlock        actionWillInvokeBlock;
@property (nonatomic, copy)   ZCActionComplation actionDidInvokeBlock;

通過這兩個回調,可以在一個請求之前,顯示相應的hud,請求完畢后顯示成功或者失敗,然后去除.

在upload action中,需要支持單文件和多文件上傳兩種方式.所以提供了2組值(data/name/filename/mime):單個的形式(NSData和NSString)以及數組的形式.

使用

沒有提供pod~~~可以把源文件拷貝,然后import "ZCApiLauncher.h"即可.

只是希望討論一個恰當的方式,實際上每個團隊都會自己維護一套適合自己的網絡庫.合適自己項目約定的才是最好的.

才疏學淺,有不對的地方請指正.

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,002評論 6 542
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,400評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,136評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,714評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,452評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,818評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,812評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,997評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,552評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,292評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,510評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,035評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,721評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,121評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,429評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,235評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,480評論 2 379

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,825評論 18 139
  • Spring Boot 參考指南 介紹 轉載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,920評論 6 342
  • 發現 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,170評論 4 61
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,733評論 18 399
  • ¥開啟¥ 【iAPP實現進入界面執行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個線程,因...
    小菜c閱讀 6,492評論 0 17