前言
这套网络请求其实是两年前封装好的,不过在多个项目中一直在用它,故此将此分享出来
问题来源
每次加载不同方式请求都要写一遍请求接口数据代码,虽说可以直接粘贴复制,不过审美观实在太差,如下
//获得请求管理者
AFHTTPSessionManager *mgr = [AFHTTPSessionManager manager];
//请求超时时间
mgr.requestSerializer.timeoutInterval = 18;
//加上此代码就可以了 声明了传过去的参数是json格式
mgr.requestSerializer = [AFJSONRequestSerializer serializer];
//#ifdef ContentType
mgr.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/plain", @"application/json", @"text/json", @"text/javascript",@"text/html", nil];
mgr.responseSerializer = [AFHTTPResponseSerializer serializer];
NSString* url = @"请求url";
NSDictionary *params = @{};
[mgr GET:url parameters:params progress:^(NSProgress * _Nonnull downloadProgress) {
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
//一顿骚操作
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
//辣眼睛操作
}];
如果别的接口是post请求,并且请求url不同,请求入参也不同,那就只能在复制一份这样的代码,只是把不同的地方换掉即可,反正粘贴复制嘛(这重复很多遍这样操作,显得很low)
解决思路
封装的核心思想简单点概括就是去重,将重复的作为参数,其余不重复的共用即可
整理好思路,那可以确定下来的就是请求方式、url、入参作为封装方法的参数,其余AFN相关代码实现为共用代码
- 创建一个类继承NSObject,我把它取名为HttpTool,按照刚刚分析创建封装好的方法,如下
- 实现逻辑,因为重点是不同的请求方式,所以需要定义枚举区别
typedef NS_ENUM(NSUInteger,RequestMethodType){
RequestGet = 1,
RequestPost = 2,
RequestPut = 3,
RequestDelete = 4,
};
@interface HttpTool : NSObject
/**
* 发送一个请求
*
* @param type 请求方法
* @param url 请求路径
* @param params 请求参数
* @param succes 请求成功后的回调(请将请求成功后想做的事情写到这个block中)
* @param failure 请求失败后的回调(请将请求失败后想做的事情写到这个block中)
*/
+(void)requestMethod:(RequestMethodType)type
url:(NSString *)url
params:(NSDictionary *)params
succes:(void (^)(id response))succes
failure:(void (^)(NSError *err))failure;
为什么多了两个block,因为AFN请求需要接受成功和失败回调,我们需要定义接受AFN请求结果作为回调
实现
+(void)requestMethod:(RequestMethodType)type
url:(NSString *)url
params:(NSDictionary *)params
succes:(void (^)(id response))succes
failure:(void (^)(NSError *err))failure{
//获得请求管理者
AFHTTPSessionManager *mgr = [AFHTTPSessionManager manager];
//请求超时时间
mgr.requestSerializer.timeoutInterval = 18;
//加上此代码就可以了 声明了传过去的参数是json格式
mgr.requestSerializer = [AFJSONRequestSerializer serializer];
//#ifdef ContentType
mgr.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/plain", @"application/json", @"text/json", @"text/javascript",@"text/html", nil];
NSString * token = [[NSUserDefaults standardUserDefaults] objectForKey:@"token"];
if (token) {
[mgr.requestSerializer setValue:token forHTTPHeaderField:@"token"];
}
url = [url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
switch (type) {
case RequestGet:{
mgr.responseSerializer = [AFHTTPResponseSerializer serializer];
[mgr GET:url parameters:params progress:^(NSProgress * _Nonnull downloadProgress) {
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
if (succes){
succes(responseObject);
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
if (failure) {
failure(error);
}
}];
}break;
case RequestPost:{
[mgr POST:url parameters:params progress:^(NSProgress * _Nonnull uploadProgress) {
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
if (succes) {
NSHTTPURLResponse *response = (NSHTTPURLResponse *)task.response;
NSDictionary *allHeaders = response.allHeaderFields;
if(allHeaders[@"token"]){
[[NSUserDefaults standardUserDefaults] setObject:allHeaders[@"token"] forKey:@"token"];
NSLog(@"%@ allHeaders",allHeaders[@"token"]);
}
NSLog(@"%@ allHeaders",allHeaders);
succes(responseObject);
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
if (failure) {
failure(error);
}
}];
}break;
case RequestPut:{
[mgr PUT:url parameters:params success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
if (succes) {
succes(responseObject);
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
if (failure) {
failure(error);
}
}];
}break;
case RequestDelete:{
[mgr DELETE:url parameters:params success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
if (succes) {
succes(responseObject);
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
if (failure) {
failure(error);
}
}];
}break;
default:
break;
}
}
至此就完事了
举例
在HttpTool头文件定义一个方法,假如是A接口的实现方法,因为我们需要成功和失败的回调,所以入参可以确认有这两个,还有一个就是接口入参(字典类型),url我建议不作为入参,原因后续讲解,如下
//版本更新
+(void)VersionUpdate:(NSDictionary *)parameter
success:(void (^)(id response))success
failure:(void (^)(NSError *err))failure;
实现
//版本更新
+(void)VersionUpdate:(NSDictionary *)parameter
success:(void (^)(id response))success
failure:(void (^)(NSError *err))failure{
NSString * url = [NSString stringWithFormat:@"%@/other/app_version",YLZDomain(Domain)];
[HttpTool requestMethod:RequestPost url:url params:parameter succes:success failure:failure];
}
YLZDomain(Domain)是定义的宏,因为我都知道有正式环境和测试环境(有些公司还有仿真环境),环境的区别也就是域名不同,所以直接两者之间切换即可。
注:url不做入参我考虑原因一为了让方法看上去简单明了,二是接口也具有封装性(YLZDomain(Domain)也算一种封装),三是不暴露接口明细