对于做开发的人来说, AFN可谓是家喻户晓. 基本上每个控制器界面都会都会涉及到网络请求, 由此可见AFN在我们开发中的重要性以及我们对AFN框架的依赖性; 之前接触过ASI的朋友应该是深有体会, 当ASI不再更新被废弃的时候, 对于程序员来说真的是晴天霹雳; 以及框架更新后程序不能正常运行, 怎么办?
这就体现了对框架封装的重要性.
新建一个类EJNetworkTool继承自AFHTTPSessionManager
单例对象
+ (instancetype)shareInstance{
static EJNetWorkTool *instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[EJNetWorkTool alloc]init]; instance.responseSerializer.acceptableContentTypes = [NSSet setWithArray:@[@"text/html"]];
});
return instance;
}
分析:
AFN中GET和POST请求暴露给我们的方法为
- (NSURLSessionDataTask *)GET:(NSString *)URLString
parameters:(id)parameters
success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
{
NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"GET" URLString:URLString parameters:parameters success:success failure:failure];
[dataTask resume];
return dataTask;
}
想一个方法搞定?? 框架中把HTTPMethod封装在下面这个方法中
- (NSURLSessionDataTask *)dataTaskWithHTTPMethod:(NSString *)method
URLString:(NSString *)URLString
parameters:(id)parameters
success:(void (^)(NSURLSessionDataTask *, id))success
failure:(void (^)(NSURLSessionDataTask *, NSError *))failure;
☺️☺️ 终于找到你; 但是问题又来了, 这是个私有方法, 我们怎么调用呢?
方法: 把这个方法抛到.h文件中, 大家用起来都开心–> 改人家框架真的好吗?
接下来我们就要想办法怎么拿到这个方法了:
思路: 自定义类中添加一个协议,把这个私有方法拷贝到代理方法中;当前类遵守协议不实现代理方法, 直接调用; 当调用这个方法的时候, 在当前类没有找到其对应的实现, 那么去父类找; 父类不就是AFHTTPSessionManager; 有木有好机智��
@protocol EJToolsDelegate
@optional
- (NSURLSessionDataTask *)dataTaskWithHTTPMethod:(NSString *)method
URLString:(NSString *)URLString
parameters:(id)parameters
success:(void (^)(NSURLSessionDataTask *dataTask, id responseObject))success
failure:(void (^)(NSURLSessionDataTask * dataTask, NSError *error))failure;
@end
定义请求类型(枚举)
typedef enum : NSUInteger {
GET,
POST
} request_Method;
实现方法
- (void)request:(request_Method)requestMethod withUrl:(NSString *)urlString parameters:(id)param callBack:(void (^)(id responseObject, NSError *error))callBack{
EJNetWorkTool *tool = [EJNetWorkTool shareInstance];
NSString *method = requestMethod == GET? @"GET" : @"POST";
[[tool dataTaskWithHTTPMethod:method URLString:urlString parameters:param success:^(NSURLSessionDataTask *dataTask, id responseObject) {
callBack(responseObject, nil);
} failure:^(NSURLSessionDataTask *dataTask, NSError *error) {
callBack(nil, error);
}]resume];
}
外部调用
- (void)loadDataWithHMTools{
EJNetWorkTool *tool = [EJNetWorkTool shareInstance];
[tool request:GET withUrl:@"http://www.weather.com.cn/data/sk/101010100.html" parameters:nil callBack:^(id responseObject, NSError *error) {
if (error != nil) {
NSLog(@"%@", error);
return ;
}
NSLog(@"%@", responseObject);
}];
}
// 备注: 使用dataTask方法一定记得resume
我们知道Swift对外界的私有方法, 除非在私有方法前加@objc才能调用到, 这又涉及到改别人框架; 所以还是采用保守做法
单例对象
static let networkTool: EJNetworkTool = {
let tools = EJNetworkTool()
tools.responseSerializer.acceptableContentTypes = NSSet(array: ["text/html"]) as Set
return tools
}()
请求类型(枚举)
enum EJRequestMethod: String{
case GET = "GET"
case POST = "POST"
}
实现
func loadData(method: EJRequestMethod, URLString: String, parameters: AnyObject?, callback: (response: AnyObject?, error: NSError?)->()){
if method == EJRequestMethod.GET{
self.GET(URLString, parameters: parameters, success: { (_, response) -> Void in
callback(response: response, error: nil)
}, failure: { (_, error) -> Void in
callback(response: nil, error: error)
})
}else{
self.POST(URLString, parameters: parameters, success: { (_, response) -> Void in
callback(response: response, error: nil)
}, failure: { (_, error) -> Void in
callback(response: nil, error: error)
})
}
}
外部调用
func networkRequest(){
let tools = EJNetworkTool.networkTool
let urlStr = "http://www.weather.com.cn/data/sk/101010100.html"
tools.loadData(.GET, URLString: urlStr, parameters: nil) { (response, error) -> () in
if error != nil{
print(error)
return
}
print(response)
}
}