圖片發自簡書App
有 AFNetworking 了,為什么還要用 YTKNetwork ? (以下1、2條文字摘自 YTKNetwork 的 readme)
- YTKNetwork 是基于 AFNetworking 封裝的,提供了一些更高級的功能。
- 支持按時間緩存網絡請求內容
- 支持按版本號緩存網絡請求內容
- 支持統一設置服務器和 CDN 的地址
- 支持檢查返回 JSON 內容的合法性
- 支持文件的斷點續傳
- 支持 block 和 delegate 兩種模式的回調方式
- 支持批量的網絡請求發送,并統一設置它們的回調(實現在 YTKBatchRequest 類中)
- 支持方便地設置有相互依賴的網絡請求的發送,例如:發送請求 A,根據請求 A 的結果,選擇性的發送請求 B 和 C,再根據 B 和 C 的結果,選擇性的發送請求 D。(實現在 YTKChainRequest 類中)
- 支持網絡請求 URL 的 filter,可以統一為網絡請求加上一些參數,或者修改一些路徑。
- 定義了一套插件機制,可以很方便地為 YTKNetwork 增加功能。猿題庫官方現在提供了一個插件,可以在某些網絡請求發起時,在界面上顯示“正在加載”的 HUD。
- YTKNetwork 的封裝運用了 command 設計模式,有如下幾個好處:
- 將網絡請求與具體的第三方庫依賴隔離,方便以后更換底層的網絡庫。實際上 YTKNetwork 最初是基于 ASIHttpRequest 的,我們只花了兩天,就很輕松地切換到了 AFNetworking。
- 方便在基類中處理公共邏輯,例如猿題庫的數據版本號信息就統一在基類中處理。
- 方便在基類中處理緩存邏輯,以及其它一些公共邏輯。
- 方便做對象的持久化。
- YTKNetwork 把每個請求都封裝成對象,代碼組織的時候可以把所有的請求類都放到一個目錄底下,我個人是比較喜歡這種組織方式。
說下 YTKNetwork 里面重要的幾個類
YTKNetworkConfig 存儲一些全局的網絡配置。比較重要的就是 baseUrl(根URL路徑)、cdnUrl(CDN服務器路徑)、urlFilters(在請求發送之前,附加到URL路徑上的一些公共參數)。
-
YTKRequest 相當于 command 設計模式中的 command。使用過程中,我們通過創建基于 YTKRequest 的網絡請求類,重寫一些父類的方法來訪問后臺。他是繼承于 YTKBaseRequest。YTKBaseRequest 類提供了開始網絡請求的便利方法。
//YTKBaseRequest 類 // 把一個請求加到隊列里面,并且開始這個請求 - (void)start; // -> 調用 YTKNetworkAgent 的 addRequest: 方法 /// 把一個請求從請求隊列里面移除掉,并且取消這個請求。 - (void)stop; // -> 調用 YTKNetworkAgent 的 cancelRequest: 方法 /// 便利請求方法,包含成功和失敗的block回調. - (void)startWithCompletionBlockWithSuccess:(nullable YTKRequestCompletionBlock)success failure:(nullable YTKRequestCompletionBlock)failure; // -> 調用 [self start] 并且設置成功和失敗的兩個回掉
-
YTKNetworkAgent 類是一個單例,相當于 command 設計模式中的接收器,發出指令的對象和被調用的對象就是通過它來實現解耦的。網絡請求的操作是在這里開始的。
//YTKNetworkAgent 類 /// 添加一個網絡請求并開始 - (void)addRequest:(YTKBaseRequest *)request; /// 取消之前添加的一個網絡請求 - (void)cancelRequest:(YTKBaseRequest *)request; /// 取消之前添加的所有網絡請求 - (void)cancelAllRequests;
-
YTKNetworkPrivate 類包含了一個工具類和一些 extension
//YTKNetworkUtils // 驗證json的有效性 + (BOOL)validateJSON:(id)json withValidator:(id)jsonValidator; // 阻止 iTunes 在應用中保存數據 + (void)addDoNotBackupAttribute:(NSString *)path; // 對字符串進行 md5 加密 + (NSString *)md5StringFromString:(NSString *)string; // 獲取 app 的版本號 + (NSString *)appVersionString;
-
YTKBatchRequest 用于方便的發送批量的請求。它是一個容器類,可以放置多個繼承于 YTKRequest 的請求實例。
// 通過一個請求數組創建一個 batch 請求 - (instancetype)initWithRequestArray:(NSArray<YTKRequest *> *)requestArray; // 開始這個 batch 請求 - (void)startWithCompletionBlockWithSuccess:(nullable void (^)(YTKBatchRequest *batchRequest))success failure:(nullable void (^)(YTKBatchRequest *batchRequest))failure;
-
YTKChainRequest 用于管理相互之間有依賴的多個請求。
// YTKChainRequest //添加一個請求并開始 - (void)addRequest:(YTKBaseRequest *)request callback:(nullable YTKChainCallback)callback; // 官方示例: - (void)sendChainRequest { // 創建一個注冊的請求 RegisterApi *reg = [[RegisterApi alloc] initWithUsername:@"username" password:@"password"]; // 創建 chain 請求實例 YTKChainRequest *chainReq = [[YTKChainRequest alloc] init]; // 開始注冊請求 [chainReq addRequest:reg callback:^(YTKChainRequest *chainRequest, YTKBaseRequest *baseRequest) { RegisterApi *result = (RegisterApi *)baseRequest; NSString *userId = [result userId]; //注冊請求完成,開始獲取個人信息的請求 GetUserInfoApi *api = [[GetUserInfoApi alloc] initWithUserId:userId]; [chainRequest addRequest:api callback:nil]; //這里仍然調用了 addRequest:callback: 方法,回調為nil }]; chainReq.delegate = self; // start to send request [chainReq start]; } // YTKChainRequestDelegate 代理 // 所有 chain 請求完成的回調 - (void)chainRequestFinished:(YTKChainRequest *)chainRequest; // 某個 chain 請求失敗的回調 - (void)chainRequestFailed:(YTKChainRequest *)chainRequest failedBaseRequest:(YTKBaseRequest*)request;