DKNetworking 基于 AFNetworking + YYCache 的網(wǎng)絡(luò)請(qǐng)求框架

前言

網(wǎng)絡(luò)層是 APP 架構(gòu)的一個(gè)重要部分博脑,蘋果的 CFNetwork 框架極其難用积仗,導(dǎo)致基于 CFN 的框架 ASI 已經(jīng)放棄維護(hù)。后來蘋果推出了 NSURLSession考润,許多開源的框架都是基于它進(jìn)行封裝棺禾,例如我選用的 AFNetworking,運(yùn)行效率沒有 ASI 高本慕,使用比 ASI 簡(jiǎn)單排拷。但是,從使用的角度來看锅尘,還需要繼續(xù)封裝监氢。于是,我依賴于 AFN + YYCache + MJExtension 封裝出了 DKNetworking 框架藤违。

特點(diǎn)

  • DKNetworkSessionManager 對(duì) AFHTTPSessionManager 進(jìn)行封裝浪腐,以便以后可以輕易換掉依賴的 AFN。封裝一層底層方法顿乒,包括網(wǎng)絡(luò)請(qǐng)求议街、文件上傳、文件下載這三個(gè)方法淆游。其中網(wǎng)絡(luò)請(qǐng)求調(diào)用了 AFN 的私有 API傍睹,把 GET隔盛、POST、PUT拾稳、DELETE吮炕、PATCH 這五個(gè)方法封成了一個(gè) request 方法。

  • 擁有 AFN 大部分常用功能访得,包括網(wǎng)絡(luò)狀態(tài)監(jiān)聽等龙亲,提供類方法和實(shí)例方法調(diào)用。

  • 根據(jù) JavaWeb 中 HttpServlet 的設(shè)計(jì)思想悍抑,把網(wǎng)絡(luò)請(qǐng)求的回調(diào)封裝成了 request 和 response 兩個(gè)對(duì)象鳄炉。

  • 支持界面多級(jí)緩存。

  • 支持鏈?zhǔn)秸{(diào)用搜骡。

  • 支持配合 RAC 框架使用鏈?zhǔn)秸{(diào)用拂盯,支持自定義信號(hào)的返回值。

安裝

支持 Cocoapods 安裝

pod 'DKNetworking'

或者下載 Demo 項(xiàng)目

  • 將根目錄下的 DKNetworking 和 Vendor 文件夾拉進(jìn)項(xiàng)目记靡,其中 Vendor 文件夾有 AFNetworking谈竿、MJExtension、YYCache 和 ReactiveCocoa摸吠,前三個(gè)是必須依賴的空凸,ReactiveCocoa 是可選的。

  • 必須在 Target -> Build Phases -> Link Binary With Libraries 中添加 libsqlite3.0.tbd寸痢,這是 YYCache 框架所需的呀洲。

使用

絕大部分方法都可以直接看 DKNetworking.h 中的聲明以及注釋。

獲取單例對(duì)象

DKNetworking *networking = [DKNetworking networkManager];

從 1.1.0 版本開始提供了一個(gè)單例對(duì)象宏 DKNetworkManager啼止。

DKN 配置

設(shè)置請(qǐng)求根路徑

[DKNetworking setupBaseURL:@"https://m.sfddj.com/app/v1/"];

baseURL 的路徑一定要有“/”結(jié)尾道逗,設(shè)置后所有的網(wǎng)絡(luò)訪問都使用相對(duì)路徑。

設(shè)置日志

開啟日志打印
[DKNetworking openLog];
關(guān)閉日志打印
[DKNetworking closeLog];

設(shè)置緩存

設(shè)置緩存方式
/**
 設(shè)置緩存方式
 DKNetworkCacheTypeNetworkOnly : 只加載網(wǎng)絡(luò)數(shù)據(jù)
 DKNetworkCacheTypeCacheNetwork : 先加載緩存,然后加載網(wǎng)絡(luò)
 @param cacheType 緩存類型
 */
+ (void)setupCacheType:(DKNetworkCacheType)cacheType;

獲取緩存大小
/**
 獲取網(wǎng)絡(luò)緩存的總大小 動(dòng)態(tài)單位(GB,MB,KB,B)

 @return 網(wǎng)絡(luò)緩存的總大小
 */
+ (NSString *)cacheSize;
清除緩存
[DKNetworkCache clearCache];

設(shè)置序列化格式

設(shè)置請(qǐng)求序列化格式
/**
 設(shè)置網(wǎng)絡(luò)請(qǐng)求參數(shù)的格式 : 默認(rèn)為二進(jìn)制格式

 @param requestSerializer DKRequestSerializerJSON:JSON格式, DKRequestSerializerHTTP:二進(jìn)制格式
 */
+ (void)setRequestSerializer:(DKRequestSerializer)requestSerializer;
設(shè)置響應(yīng)反序列化格式
/**
 設(shè)置服務(wù)器響應(yīng)數(shù)據(jù)格式 : 默認(rèn)為JSON格式

 @param responseSerializer DKResponseSerializerJSON:JSON格式, DKResponseSerializerHTTP:二進(jìn)制格式
 */
+ (void)setResponseSerializer:(DKResponseSerializer)responseSerializer;

設(shè)置請(qǐng)求超時(shí)時(shí)間

/**
 設(shè)置請(qǐng)求超時(shí)時(shí)間 : 默認(rèn)10秒

 @param time 請(qǐng)求超時(shí)時(shí)長(zhǎng)(秒)
 */
+ (void)setRequestTimeoutInterval:(NSTimeInterval)time;

設(shè)置 Header

設(shè)置一對(duì)請(qǐng)求頭參數(shù)
/**
 設(shè)置一對(duì)請(qǐng)求頭參數(shù)

 @param value 請(qǐng)求頭參數(shù)值
 @param field 請(qǐng)求頭參數(shù)名
 */
+ (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field;
設(shè)置多對(duì)請(qǐng)求頭參數(shù)
/**
 設(shè)置多對(duì)請(qǐng)求頭參數(shù)

 @param networkHeader 請(qǐng)求頭參數(shù)字典
 */
+ (void)setNetworkHeader:(NSDictionary *)networkHeader;

網(wǎng)絡(luò)狀態(tài)

監(jiān)聽網(wǎng)絡(luò)狀態(tài)

[DKNetworking networkStatusWithBlock:^(DKNetworkStatus status) {
    switch (status) {
        case DKNetworkStatusUnknown: // 網(wǎng)絡(luò)狀態(tài)未知
            break;
        case DKNetworkStatusNotReachable: // 無網(wǎng)絡(luò)
            break;
        case DKNetworkStatusReachableViaWWAN: // 手機(jī)網(wǎng)絡(luò)(蜂窩)
            break;
        case DKNetworkStatusReachableViaWiFi: // WIFI網(wǎng)絡(luò)
            break;
    }
}];

獲取當(dāng)前網(wǎng)絡(luò)狀態(tài)

/**
 有網(wǎng)絡(luò):YES, 無網(wǎng)絡(luò):NO
 */
+ (BOOL)isNetworking;

/**
 手機(jī)網(wǎng)絡(luò):YES, 非手機(jī)網(wǎng)絡(luò):NO
 */
+ (BOOL)isWWANNetwork;

/**
 WiFi網(wǎng)絡(luò):YES, 非WiFi網(wǎng)絡(luò):NO
 */
+ (BOOL)isWiFiNetwork;

網(wǎng)絡(luò)請(qǐng)求

常規(guī)調(diào)用

以 POST 方法為例族壳,方法定義:

/**
 POST請(qǐng)求
 
 @param URL 請(qǐng)求地址
 @param parameters 請(qǐng)求參數(shù)
 @param callback 請(qǐng)求回調(diào)
 @return 返回的對(duì)象可取消請(qǐng)求,調(diào)用cancel方法
 */
+ (NSURLSessionTask *)POST:(NSString *)URL parameters:(NSDictionary *)parameters callback:(DKNetworkBlock)callback;
- (NSURLSessionTask *)POST:(NSString *)URL parameters:(NSDictionary *)parameters callback:(DKNetworkBlock)callback;

調(diào)用:

[DKNetworking POST:url parameters:@{@"name":@"bingo"} callback:^(DKNetworkRequest *request, DKNetworkResponse *response) {
    // ...
}];

鏈?zhǔn)秸{(diào)用

方法定義:

/** 鏈?zhǔn)秸{(diào)用 */
- (DKNetworking *(^)(NSString *url))get;
- (DKNetworking *(^)(NSString *url))post;
- (DKNetworking *(^)(NSString *url))put;
- (DKNetworking *(^)(NSString *url))delete;
- (DKNetworking *(^)(NSString *url))patch;
- (DKNetworking *(^)(NSDictionary *params))params;
- (DKNetworking *(^)(NSDictionary *header))header;
- (DKNetworking *(^)(DKNetworkCacheType cacheType))cacheType;
- (DKNetworking *(^)(DKRequestSerializer requestSerializer))requestSerializer;
- (DKNetworking *(^)(DKResponseSerializer responseSerializer))responseSerializer;
- (DKNetworking *(^)(DKRequestTimeoutInterval requestTimeoutInterval))requestTimeoutInterval;
- (void(^)(DKNetworkBlock networkBlock))callback;

調(diào)用:

DKNetworkManager.post(url).params(@{@"name":@"bingo"}).callback(^(DKNetworkRequest *request, DKNetworkResponse *response) {
    // ...
});

RAC 鏈?zhǔn)秸{(diào)用

方法定義:

在原鏈?zhǔn)椒椒ǖ幕A(chǔ)上補(bǔ)充了一個(gè) executeSignal 方法憔辫,返回信號(hào)。

#ifdef RAC
/** RAC鏈?zhǔn)桨l(fā)送請(qǐng)求 */
- (RACSignal *)executeSignal;
#endif

調(diào)用:

[DKNetworkManager.post(url).params(@{@"name":@"bingo"}).executeSignal subscribeNext:^(RACTuple *x) {
    DKNetworkResponse *response = x.second;
    // ...
} error:^(NSError *error) {
    // ...
}];

RAC 鏈?zhǔn)秸{(diào)用 自定義信號(hào)的返回值

方法定義:

#ifdef RAC
/**
 設(shè)置響應(yīng)結(jié)果回調(diào)仿荆,可以設(shè)置信號(hào)返回的value為自己想要的值,比如用MJExtension框架坏平,將DKNetworkResponse對(duì)象的rawData字典轉(zhuǎn)為自己項(xiàng)目的實(shí)體類再返回
 
 @param flattenMapBlock 結(jié)果映射的設(shè)置回調(diào)block拢操,其中RACTuple的first為DKNetworkRequest對(duì)象,second為DKNetworkResponse對(duì)象
 */
+ (void)setupResponseSignalWithFlattenMapBlock:(DKNetworkFlattenMapBlock)flattenMapBlock;
#endif

使用:

考慮到代碼執(zhí)行順序的問題舶替,建議在項(xiàng)目中創(chuàng)建一個(gè)繼承自 NSObject 的類 DKNetworkConfig令境,在 + load 方法中調(diào)用 DKN 的配置方法,設(shè)置回調(diào)的信號(hào)的 return 值顾瞪,根據(jù)不同項(xiàng)目進(jìn)行配置舔庶。

[DKNetworking setupResponseSignalWithFlattenMapBlock:^RACStream *(RACTuple *tuple) {
    DKNetworkResponse *response = tuple.second; // 框架默認(rèn)返回的response
    MyHttpResponse *myResponse = [MyHttpResponse mj_objectWithKeyValues:response.rawData]; // 項(xiàng)目需要的response
    myResponse.rawData = response.rawData;
    myResponse.error = response.error;
    return [RACSignal return:RACTuplePack(tuple.first, myResponse)];
}];

調(diào)用:

經(jīng)過上面的setupResponseSignalWithFlattenMapBlock:方法設(shè)置后抛蚁,信號(hào)返回的 RACTuple 的 second 為自定義的 response 對(duì)象。

[DKNetworkManager.post(url).executeSignal subscribeNext:^(RACTuple *x) {
//        DKNetworkResponse *response = x.second;
    MyHttpResponse *myResponse = x.second;
    // ...
} error:^(NSError *error) {
    // ...
}];

取消請(qǐng)求

/**
 取消所有HTTP請(qǐng)求
 */
+ (void)cancelAllRequest;

/**
 取消指定URL的HTTP請(qǐng)求
 */
+ (void)cancelRequestWithURL:(NSString *)URL;

上傳

上傳文件
/**
 上傳文件

 @param URL 請(qǐng)求地址
 @param parameters 請(qǐng)求參數(shù)
 @param name 文件對(duì)應(yīng)服務(wù)器上的字段
 @param filePath 文件本地的沙盒路徑
 @param progressBlock 上傳進(jìn)度回調(diào)
 @param callback 請(qǐng)求回調(diào)
 @return 返回的對(duì)象可取消請(qǐng)求,調(diào)用cancel方法
 */
+ (NSURLSessionTask *)uploadFileWithURL:(NSString *)URL
                             parameters:(NSDictionary *)parameters
                                   name:(NSString *)name
                               filePath:(NSString *)filePath
                          progressBlock:(DKNetworkProgressBlock)progressBlock
                               callback:(void(^)(DKNetworkResponse *response))callback;
上傳圖片
/**
 上傳圖片

 @param URL 請(qǐng)求地址
 @param parameters 請(qǐng)求參數(shù)
 @param name 圖片對(duì)應(yīng)服務(wù)器上的字段
 @param images 圖片數(shù)組
 @param fileNames 圖片文件名數(shù)組惕橙,傳入nil時(shí)數(shù)組內(nèi)的文件名默認(rèn)為當(dāng)前日期時(shí)間戳+索引
 @param imageScale 圖片文件壓縮比 范圍 (0.f ~ 1.f)
 @param imageType 圖片文件的類型瞧甩,例:png、jpg(默認(rèn)類型)....
 @param progressBlock 上傳進(jìn)度回調(diào)
 @param callback 請(qǐng)求回調(diào)
 @return 返回的對(duì)象可取消請(qǐng)求,調(diào)用cancel方法
 */
+ (NSURLSessionTask *)uploadImagesWithURL:(NSString *)URL
                               parameters:(NSDictionary *)parameters
                                     name:(NSString *)name
                                   images:(NSArray<UIImage *> *)images
                                fileNames:(NSArray<NSString *> *)fileNames
                               imageScale:(CGFloat)imageScale
                                imageType:(NSString *)imageType
                            progressBlock:(DKNetworkProgressBlock)progressBlock
                                 callback:(void(^)(DKNetworkResponse *response))callback;

下載

/**
 下載文件

 @param URL 請(qǐng)求地址
 @param fileDir 文件存儲(chǔ)目錄(默認(rèn)存儲(chǔ)目錄為Download)
 @param progressBlock 文件下載的進(jìn)度回調(diào)
 @param callback 請(qǐng)求回調(diào)弥鹦,filePath為文件保存路徑
 @return 返回 NSURLSessionDownloadTask 實(shí)例肚逸,可用于暫停繼續(xù),暫停調(diào)用 suspend 方法彬坏,開始下載調(diào)用 resume 方法
 */
+ (NSURLSessionTask *)downloadWithURL:(NSString *)URL
                              fileDir:(NSString *)fileDir
                        progressBlock:(DKNetworkProgressBlock)progressBlock
                             callback:(void(^)(NSString *filePath, NSError *error))callback;

TODO

  • 鏈?zhǔn)骄幊屉m然好看一點(diǎn)朦促,但是沒有常規(guī)調(diào)用方便,不能像以往一樣敲兩個(gè)字母 Xcode 就智能補(bǔ)全整個(gè)方法栓始,并且可能會(huì)出現(xiàn) .get().post().get().post() 這種沒有意義的鏈?zhǔn)秸{(diào)用的情況务冕。

  • 用面向協(xié)議(接口)的函數(shù)式編程可以解決上面的問題,但是網(wǎng)絡(luò)層工具的調(diào)用是可以沒有順序的幻赚,比如 .params().post().post().params() 應(yīng)該是都可以的洒疚,這樣的話會(huì)讓協(xié)議很難制定,還是會(huì)出現(xiàn)上面的問題坯屿。

  • 日志保存文件

  • 考慮添加 UI 層分類油湖,讓網(wǎng)絡(luò)請(qǐng)求的錯(cuò)誤日志以一種更友好的方式展示。

  • 與服務(wù)端的通訊加密领跛,考慮添加 RSA 非對(duì)稱加密等方法乏德。

后話

DKNetworking 框架源碼已經(jīng)托管在 GitHub,遵循 MIT 協(xié)議吠昭。歡迎向我們發(fā)起 PR 貢獻(xiàn)您的代碼喊括,或者有什么建議歡迎 Issues。如果對(duì)您有幫助矢棚,請(qǐng)給予 star郑什,你們的支持是我奮斗的動(dòng)力,謝謝蒲肋!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末蘑拯,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子兜粘,更是在濱河造成了極大的恐慌申窘,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,185評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件孔轴,死亡現(xiàn)場(chǎng)離奇詭異剃法,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)路鹰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門贷洲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來收厨,“玉大人,你說我怎么就攤上這事优构∷腥” “怎么了?”我有些...
    開封第一講書人閱讀 163,524評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵俩块,是天一觀的道長(zhǎng)黎休。 經(jīng)常有香客問我,道長(zhǎng)玉凯,這世上最難降的妖魔是什么势腮? 我笑而不...
    開封第一講書人閱讀 58,339評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮漫仆,結(jié)果婚禮上捎拯,老公的妹妹穿的比我還像新娘。我一直安慰自己盲厌,他們只是感情好署照,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評(píng)論 6 391
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著吗浩,像睡著了一般建芙。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上懂扼,一...
    開封第一講書人閱讀 51,287評(píng)論 1 301
  • 那天禁荸,我揣著相機(jī)與錄音,去河邊找鬼阀湿。 笑死赶熟,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的陷嘴。 我是一名探鬼主播映砖,決...
    沈念sama閱讀 40,130評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼灾挨!你這毒婦竟也來了邑退?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,985評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤涨醋,失蹤者是張志新(化名)和其女友劉穎瓜饥,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體浴骂,經(jīng)...
    沈念sama閱讀 45,420評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評(píng)論 3 334
  • 正文 我和宋清朗相戀三年宪潮,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了溯警。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片趣苏。...
    茶點(diǎn)故事閱讀 39,779評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖梯轻,靈堂內(nèi)的尸體忽然破棺而出食磕,到底是詐尸還是另有隱情,我是刑警寧澤喳挑,帶...
    沈念sama閱讀 35,477評(píng)論 5 345
  • 正文 年R本政府宣布彬伦,位于F島的核電站,受9級(jí)特大地震影響伊诵,放射性物質(zhì)發(fā)生泄漏单绑。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評(píng)論 3 328
  • 文/蒙蒙 一曹宴、第九天 我趴在偏房一處隱蔽的房頂上張望搂橙。 院中可真熱鬧,春花似錦笛坦、人聲如沸区转。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)废离。三九已至,卻和暖如春礁芦,著一層夾襖步出監(jiān)牢的瞬間蜻韭,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工宴偿, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留湘捎,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,876評(píng)論 2 370
  • 正文 我出身青樓窄刘,卻偏偏與公主長(zhǎng)得像窥妇,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子娩践,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評(píng)論 2 354

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

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)活翩、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,098評(píng)論 4 62
  • AFHTTPRequestOperationManager 網(wǎng)絡(luò)傳輸協(xié)議UDP翻伺、TCP材泄、Http、Socket吨岭、X...
    Carden閱讀 4,337評(píng)論 0 12
  • 人格即性格拉宗,人格特質(zhì)就表現(xiàn)為人們對(duì)身邊環(huán)境和自己個(gè)性的慣常看待方式,以及行為舉止和做出反應(yīng)的習(xí)慣方式旦事。 特質(zhì)與狀態(tài)...
    生銹的木魚閱讀 1,090評(píng)論 0 2
  • 今天早晨聽擁抱內(nèi)在小孩的cd魁巩,結(jié)果又遇見一個(gè)虛弱的小孩,那個(gè)小孩那么渴望得到一次感冒自愈的機(jī)會(huì)姐浮,可是無論如何媽媽也...
    曼谷123閱讀 158評(píng)論 0 0
  • 閱讀時(shí)間:2016年6月13日谷遂,19:00-21:30;2.5小時(shí)卖鲤; 閱讀書本:《美物抵心》肾扰,作者:【日】赤木明登...
    時(shí)空山莊閱讀 236評(píng)論 0 0