iOS開發--OC網絡請求中網絡中間層的使用
我們平常的網絡數據請求,在開發中用到最多的網絡請求框架是AFN框架,程序中的我們每一個ViewController都是通過AFN的request來獲取數據。每一個ViewController和AFN,還有服務器的關系就像下面第一張圖片那樣。
在實際開發中使用這種方式來請求數據是可以正常獲取到網絡中的數據。但會存在一個風險,就是如果有一天,AFN框架的作者去追求詩和遠方了,框架不再進行更新。不能適配最新的系統。或者我們的產品經理和項目經理突發奇想,覺得用AFN框架已經不能滿足公司的網絡請求功能,需要修改。這個時候我們要修改代碼中的網絡請求。就要找到每一句使用AFN請求網絡數據的代碼,然后再換成其他能夠適配最新操作系統的框架。這個過程肯定非常麻煩。但要解決這個問題,方法卻很簡單。我們只需要將第一張圖中控制器和AFN的關系變為第二張圖中的關系。新建一個網絡請求的工具類。在工具類中,封裝網絡請求的方法,方法中使用AFN框架。使用這種方式請求數據,控制器是通過網絡請求工具進行數據請求,是一對多的關系。網絡請求工具類中使用的是AFN框架,是一對一的關系。如果我們想要修改網絡請求使用的框架,就只需要將網絡請求工具類中使用的AFN框架,替換成一個新的框架。就能一步將網絡請求使用的框架進行替換。
2.png
接下來就要一步一步地分析這是怎么實現的。
下面的一段代碼是正常的使用AFN去請求網絡數據的方法。
//這個是使用AFN獲取網絡數據的方法
-(void)loadData
{
//使用AFN請求網絡數據
[[AFHTTPSessionManager manager]GET:@"https://httpbin.org/get?name=xiaoming" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
//打印響應數據
NSLog(@"%@",responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
//打印錯誤信息
NSLog(@"%@",error);
}];
}
接下來的代碼就是要將網絡請求封裝成一個工具類。我們通過自定義一個類,在類中提供網絡請求的方法,將網絡請求需要的參數通過方法的參數傳遞進去。然后在方法內部去判斷GET請求還是POST請求,最后發起請求。
- (void)retuest:(NSString *)URLString
method:(NSString *)method
parameters:(NSDictionary *)parameters
callBack:(void(^)(id responsnose)) callBack
{
//在沒獲取到更深入一層的方法之前,判斷后再去使用GET 或者 POST方法。
if ([method isEqualToString:@"GET"]) {
[self GET:URLString parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
callBack(responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"%@",error);
callBack(error);
}];
}
if ([method isEqualToString:@"POST"]) {
[self POST:URLString parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
callBack(responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"%@",error);
callBack(error);
}];
}
}
做完上面一步后,我們去查看AFN內部的代碼發現,不管是POST請求還是GET請求。最后都是調用下面這個方法。沒想到AFN是這樣的AFN。所以我們可以試著去獲取到類內部的方法,從而將代碼進行簡化。
- (NSURLSessionDataTask *)POST:(NSString *)URLString
parameters:(id)parameters
progress:(void (^)(NSProgress * _Nonnull))uploadProgress
success:(void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success
failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure
{
//不管是GET請求,還是POST請求,在AFN中最后都會調用到這個方法
NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"POST" URLString:URLString parameters:parameters uploadProgress:uploadProgress downloadProgress:nil success:success failure:failure];
[dataTask resume];
return dataTask;
}
- (NSURLSessionDataTask *)GET:(NSString *)URLString
parameters:(id)parameters
progress:(void (^)(NSProgress * _Nonnull))downloadProgress
success:(void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success
failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure
{
//不管是GET請求,還是POST請求,在AFN中最后都會調用到這個方法
NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"GET"
URLString:URLString
parameters:parameters
uploadProgress:nil
downloadProgress:downloadProgress
success:success
failure:failure];
[dataTask resume];
return dataTask;
}
既然不管是GET請求,還是POST請求,在AFN中最后都會調用到這個方法。我們就可以嘗試著用這一個方法替換掉上面的GET 和 POST兩個方法。這樣子我們的代碼就能進一步簡化。但是這個方法在AFURLSessionManager內部的方法,通過我們自定義的工具類肯定不能直接來調用。這個時候,我們就需要使用到OC中的黑魔法,就是通過OC的運行時機制,來調用框架內部的方法。但要注意,這種方法不是很正統。因為是通過運行時去獲取到框架作者封裝在內部的方法。但是在原理上來說是可行的,開發中是不是用全看實際項目的需求。只是說知道這些方法會讓你可以在同事面前秀下優越,除此之外,還是少用。下面是具體的代碼。
我們在NetWorkTool.m文件中定義一個協議,并且在協議中聲明我們上面討論的AFN內部的方法,我們讓網絡工具類去遵守這個協議。這樣,我們自定義的網絡工具類就能“愉快”地使用AFN內部的方法了。
#import "NetWorkTool.h"
#import "AFNetworking.h"
//黑魔法
@protocol AFNetworkingDelagete <NSObject>
@optional
- (NSURLSessionDataTask *)dataTaskWithHTTPMethod:(NSString *)method
URLString:(NSString *)URLString
parameters:(id)parameters
uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgress
downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgress
success:(void (^)(NSURLSessionDataTask *, id))success
failure:(void (^)(NSURLSessionDataTask *, NSError *))failure;
@end
@interface NetWorkTool ()<AFNetworkingDelagete>
@end
來自:http://www.jianshu.com/p/26c93df1ac5e