引言
iOS9.0之后,NSURLConnection被苹果抛弃,该来的即便是迟些,但最终肯定会来。对于迷恋NSURLConnection还要适配iOS低版本的公司,就不得不三思了,当然,使用NSURLSession也是不错的,但面对成熟的ASI和AFN,我们更有理由选择。
正题
开始看到这个题目,很多人会有疑问:ASI和AFN都是很成熟的三方库,为什么要再次封装呢?
对此,我的理解是,对于咨讯、新闻类APP,或许不需要,它们主要以刷流量为主,直接使用(很适合我们抓包拿来练手)。但对于安全性要求较高的APP而言,它们需要的是有效流量,这时一般要对自己的URL进行加密,比如:“支付”类、会员视频点播等。如果URL加密的话,对ASI或AFN二次封装就要提上日程啦,当然这也是对其进行二次封装的作用及意义所在。
URL加密
我们采用方式比较简易,在URL的head中,添加动态token及User-Agent添加des加密字符的方式等,起到加密效果。
引入ASI和AFN SDK(最终项目选其一)
本人使用CocoaPods三方库管理工具
platform :ios,’7.0’
target ‘MMBao_master’ do
pod 'ASIHTTPRequest'
pod 'AFNetworking', '~> 3.0'
......
end
一、ASIHTTPRequest再封装
1、ASIHTTPRequest异步请求及ASIHTTPRequestDelegate简析
ASI是iOS知名度最高的网络请求三方库,由于它的实现是基于底层的CFNetwork框架,运行效率较其他网络请求库都要高出一筹。
ASIHTTPRequest异步请求
(1)创建网络请求
NSURL *url = [NSURL URLWithString:@"http://192.168.1.111:8080/ProjectName/getToken];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
request.timeOutSeconds = 30; // 超时设置
(2)统一为请求添加head,如:Date 提供日期和时间标志、Content-Length请求内容的长度、Content-Type请求与实体对应的MIME信息等;或者添加自定义header的类型,比如特定用户标记信息,加密信息token等。
[request addRequestHeader:@"phone_type" value:@"iOS"];
[manager.requestSerializer setValue:tokenDes forHTTPHeaderField:@"token"];
......
(3)设置ASIHTTPRequestDelegate代理
request.delegate = self;
(4)发送异步请求
[request startAsynchronous];
ASIHTTPRequestDelegate简析
(1)网络请求start
- (void)requestStarted:(ASIHTTPRequest *)request
(2)开始接收到服务器的数据
- (void)request:(ASIHTTPRequest *)request didReceiveData:(NSData *)data
(3)请求成功完毕
- (void)requestFinished:(ASIHTTPRequest *)request
(4)请求失败
- (void)requestFailed:(ASIHTTPRequest *)request
(5)取消请求,切记
[request clearDelegatesAndCancel];
2、EVNASIConnectionUtil工具类实现
EVNASIConnectionUtil.h
//
// EVNASIConnectionUtil.h
// MMBao_master
//
// Created by developer on 16/8/24.
// Copyright © 2016年 仁伯安. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "ASIHTTPRequest.h"
#pragma mark - 请求方法
typedef NS_ENUM(NSUInteger, ASIURLMethod)
{
ASIPOST = 1,
ASIGET = 2,
};
#pragma mark - TAG定义,命名规则: URL开头+模块名字+Tag
typedef NS_ENUM(NSUInteger, ASIURLTag)
{
#pragma mark: 账户管理
ASIURLGetTokenTag,
#pragma mark - 登录及注册
#pragma mark: 三方登录
#pragma mark - 分类及热词搜索
#pragma mark - 买家模块
};
#pragma mark - 返回的Result
typedef NS_ENUM(NSUInteger, ASIResultCode)
{
ASIRS_Success = 1,
ASIRS_Error,
};
@protocol ASIHTTPConnectionDelegate <NSObject>
@optional
@required
/**
* 网络请求完成(包括数据返回成功、失败、接口超时)后的回调方法
*
* @param dicRespon 网络请求后返回的JSON数据
* @param URLTag 网络请求的标识tag
* @param theResultCode 状态码,成功 && 失败
* @param res 网络请求返回的result,一般1表示请求成功,0表示请求失败
* @param message 提示信息
* @param failStatus 是否显示网络请求异常图片
*/
- (void)resultWithDic:(NSDictionary *)dicRespon urlTag:(ASIURLTag)URLTag isSuccess:(ASIResultCode)theResultCode Result:(int) res Message:(NSString *) message failImage:(int) failStatus;
@optional
- (void) resultWithString:(NSString *) str;
@end
#pragma mark - EVNASIConnectionUtil工具类
@interface EVNASIConnectionUtil : NSObject<ASIHTTPRequestDelegate>
{
NSMutableData *_dtReviceData;
int FailStatus;
}
@property (nonatomic, assign) id<ASIHTTPConnectionDelegate> delegate;
@property (nonatomic, assign) ASIURLTag urlTag;
@property (nonatomic, strong) ASIHTTPRequest *conn;
/**
* 网络请求初始化方法
*
* @param theUrlTag 网络请求的标识tag
* @param theDelegate 网络请求代理
*
* @return ASIHTTP实例
*/
- (instancetype)initWithURLTag:(ASIURLTag)theUrlTag delegate:(id<ASIHTTPConnectionDelegate>)theDelegate;
/**
* common 网络请求
*
* @param strUrl URL服务器地址
* @param strPostBody body
* @param theMethod 网络请求方式,比如GET、POST
*/
- (void)getResultFromUrlString:(NSString *)strUrl postBody:(NSString *)strPostBody method:(ASIURLMethod)theMethod;
/**
* 上传图片音频 网络请求
*
* @param strUrl URL服务器地址
* @param dicText 需要的参数,dicImage表示,strImageFileName表示
* @param dicImage 图片名字
* @param strImageFileName 服务器端文件的目录名
* @param avFile 音频类网络请求文件名
*/
- (void)getResultFromUrlString:(NSString *)strUrl dicText:(NSDictionary *)dicText dicImage:(NSDictionary *)dicImage imageFilename:(NSMutableArray *)strImageFileName WithAVFile:(NSString *) avFile;
/**
* 网络请求结束,终止
*/
- (void)stopConnection;
#pragma mark -
- (void)getResultFromUrlString:(NSString *)strUrl postBody:(NSMutableArray *)strPostBodyArray postArg:(NSMutableArray *) argArray method:(ASIURLMethod)theMethod failImage:(int) faileSatatus;
@end
EVNASIConnectionUtil.m
//
// EVNASIConnectionUtil.m
// MMBao_master
//
// Created by developer on 16/8/24.
// Copyright © 2016年 仁伯安. All rights reserved.
//
#import "EVNASIConnectionUtil.h"
#import "AppDelegate.h"
#import "MCdes.h"
#import <AVFoundation/AVFoundation.h>
#define KEYPassWordMCdes @"加密字符"
@implementation EVNASIConnectionUtil
{
AppDelegate *appDel;
NSString *tokenDes;
}
- (instancetype)initWithURLTag:(ASIURLTag)theUrlTag delegate:(id<ASIHTTPConnectionDelegate>)theDelegate
{
self = [super init];
if (self)
{
self.delegate = theDelegate;
self.urlTag = theUrlTag;
appDel = (AppDelegate *)[UIApplication sharedApplication].delegate;
tokenDes = appDel.appToken;
if([self validateString:tokenDes] == NO)
{
tokenDes = @"";
}
}
return self;
}
// URL编码
- (NSString *)encodeToPercentEscapeString: (NSString *) input
{
NSString *outputStr = (NSString *) CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)input, NULL, (CFStringRef)@"!*'();:@=+$,/?%#[]", kCFStringEncodingUTF8));
return outputStr;
}
- (void)getResultFromUrlString:(NSString *)strUrl postBody:(NSMutableArray *)strPostBodyArray postArg:(NSMutableArray *)argArray method:(ASIURLMethod)theMethod failImage:(int)faileSatatus
{
FailStatus = faileSatatus;
strUrl = [strUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSMutableString *strPostBody = [[NSMutableString alloc] initWithString:@""];
for(NSInteger i=0;i<argArray.count;i++)
{
NSString *bodyStr = [[strPostBodyArray objectAtIndex:i] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *argStr = [self encodeToPercentEscapeString:[NSString stringWithFormat:@"%@",[argArray objectAtIndex:i]]];
NSString *s = [NSString stringWithFormat:@"%@%@",bodyStr,argStr];
[strPostBody appendString:s];
}
NSString *urlStr;
if([self validateString:strPostBody] == NO)
{
urlStr = [NSString stringWithFormat:@"%@",strUrl];
}
else
{
urlStr = [NSString stringWithFormat:@"%@%@",strUrl,strPostBody];
}
NSLog(@"请求接口:%@",urlStr);
ASIHTTPRequest *request = [[ASIHTTPRequest alloc]initWithURL:[NSURL URLWithString:urlStr]];
[request setValidatesSecureCertificate:NO];//请求https的时候,需要设置该属性
request.timeOutSeconds = 30;
//设置传送类型
NSString *contentType = [NSString stringWithFormat:@"application/x-www-form-urlencoded"];
//给传输类型添加内容
[request addRequestHeader:@"Content-Type" value:contentType];
#pragma mark - 修改header头
NSString *dataDes = [MCdes encryptUseDES:@"需要加密的字符" key:KEYPassWordMCdes];
[request addRequestHeader:@"User-Agent" value:dataDes];
[request addRequestHeader:@"token" value:tokenDes];
......
[request addRequestHeader:@"phone_type" value:@"应用缩写_iOS"];
if (theMethod == ASIGET)
{
[request setRequestMethod:@"GET"];
}
else
{
[request setRequestMethod:@"POST"];
}
[[UIApplication sharedApplication]setNetworkActivityIndicatorVisible:YES];
request.delegate = self;
self.conn = request;
[self.conn startAsynchronous];
}
#pragma mark - 异步请求数据,strUrl表示域名,strPostBody表示上传的参数,theMethod表示请求方式
- (void)getResultFromUrlString:(NSString *)strUrl postBody:(NSString *)strPostBody method:(ASIURLMethod)theMethod
{
strUrl = [strUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
strPostBody = [strPostBody stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *urlStr;
if([self validateString:strPostBody] == NO)
{
urlStr = [NSString stringWithFormat:@"%@",strUrl];
}
else
{
urlStr = [NSString stringWithFormat:@"%@%@",strUrl,strPostBody];
}
NSLog(@"请求接口:%@",urlStr);
ASIHTTPRequest *request = [[ASIHTTPRequest alloc]initWithURL:[NSURL URLWithString:urlStr]];
[request setValidatesSecureCertificate:NO];//请求https的时候,需要设置该属性
request.timeOutSeconds = 30;
//设置传送类型
NSString *contentType = [NSString stringWithFormat:@"application/x-www-form-urlencoded"];
//给传输类型添加内容
[request addRequestHeader:@"Content-Type" value:contentType];
#pragma mark - 修改header头
NSString *dataDes = [MCdes encryptUseDES:@"需要加密的字符" key:KEYPassWordMCdes];
[request addRequestHeader:@"User-Agent" value:dataDes];
[request addRequestHeader:@"token" value:tokenDes];
......
[request addRequestHeader:@"phone_type" value:@"应用缩写_iOS"];
if (theMethod == ASIGET)
{
[request setRequestMethod:@"GET"];
}
else
{
[request setRequestMethod:@"POST"];
}
[[UIApplication sharedApplication]setNetworkActivityIndicatorVisible:YES];
request.delegate = self;
self.conn = request;
[self.conn startAsynchronous];
}
#pragma mark - POST上传图片,strUrl表示服务器地址,dicText表示需要的参数,dicImage表示图片名字,strImageFileName表示上传到服务器的目录
- (void)getResultFromUrlString:(NSString *)strUrl dicText:(NSDictionary *)dicText dicImage:(NSDictionary *)dicImage imageFilename:(NSMutableArray *)strImageFileName WithAVFile:(NSString *) avFile
{
NSLog(@"strUrl = %@",strUrl);
NSString *url = strUrl;
//分界线的标识符
NSString *TWITTERFON_FORM_BOUNDARY = @"AaB03x";
//根据url初始化request
ASIHTTPRequest *request = [[ASIHTTPRequest alloc]initWithURL:[NSURL URLWithString:url]];
[request setValidatesSecureCertificate:NO];//请求https的时候,需要设置该属性
request.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
request.timeOutSeconds = 30;
//分界线 --AaB03x
NSString *MPboundary=[[NSString alloc]initWithFormat:@"--%@",TWITTERFON_FORM_BOUNDARY];
//结束符 AaB03x--
NSString *endMPboundary=[[NSString alloc]initWithFormat:@"%@--",MPboundary];
//http body的字符串
NSMutableString *body=[[NSMutableString alloc]init];
for (NSString *strKey in [dicText allKeys])
{
NSString *strValue = [dicText objectForKey:strKey];
[body appendFormat:@"\r\n--%@\r\ncontent-disposition: form-data; name=\"%@\"\r\n\r\n%@",TWITTERFON_FORM_BOUNDARY,strKey,strValue];
}
//添加分界线,换行
[body appendString:@"\r\n"];
NSMutableArray *aryBody = [[NSMutableArray alloc]init];
for(int i=0;i<[[dicImage allKeys] count];i++)
{
NSString *strImageKey = [NSString stringWithFormat:@"%@",[[dicImage allKeys] objectAtIndex:i]];
NSMutableString *strBody = [[NSMutableString alloc]init];
[strBody appendFormat:@"\r\n%@\r\n",MPboundary];
NSString *S = [NSString stringWithFormat:@"%@",[strImageFileName objectAtIndex:i]];
//声明pic字段,文件名
[strBody appendFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n",S,strImageKey];
[strBody appendString:@"Content-Type: multipart/form-data\r\n\r\n"];
[aryBody addObject:strBody];
}
//声明结束符:--AaB03x--
NSString *end=[[NSString alloc]initWithFormat:@"\r\n%@",endMPboundary];
//声明myRequestData,用来放入http body
NSMutableData *myRequestData=[NSMutableData data];
//将body字符串转化为UTF8格式的二进制
[myRequestData appendData:[body dataUsingEncoding:NSUTF8StringEncoding]];
for (int i = 0 ; i<[[dicImage allValues] count]; i++)
{
NSString *strBody = [aryBody objectAtIndex:i];
id test = [[dicImage allValues] objectAtIndex:i];
if([test isKindOfClass:[UIImage class]])
{
UIImage *imgUpload = [[dicImage allValues] objectAtIndex:i];
//上传图片格式为png,可以更改为jpeg,同时需要更改文件名
NSData *dtImg = UIImagePNGRepresentation(imgUpload);
[myRequestData appendData:[strBody dataUsingEncoding:NSUTF8StringEncoding]];
[myRequestData appendData:dtImg];
}
else if([test isKindOfClass:[AVURLAsset class]])
{
NSData *data = [NSData dataWithContentsOfFile:avFile];
[myRequestData appendData:[strBody dataUsingEncoding:NSUTF8StringEncoding]];
[myRequestData appendData:data];
}
}
//加入结束符--AaB03x--
[myRequestData appendData:[end dataUsingEncoding:NSUTF8StringEncoding]];
//设置HTTPHeader中Content-Type的值
NSString *content = [[NSString alloc]initWithFormat:@"multipart/form-data; boundary=%@",TWITTERFON_FORM_BOUNDARY];
//设置HTTPHeader
[request addRequestHeader:@"Content-Type" value:content];
#pragma mark - 修改header头
NSString *dataDes = [MCdes encryptUseDES:@"需要加密的字符" key:KEYPassWordMCdes];
[request addRequestHeader:@"User-Agent" value:dataDes];
[request addRequestHeader:@"token" value:tokenDes];
......
[request addRequestHeader:@"phone_type" value:@"应用缩写_iOS"];
//设置Content-Length
[request addRequestHeader:@"Content-Length" value:[NSString stringWithFormat:@"%lu", (unsigned long)[myRequestData length]]];
[request setRequestMethod:@"POST"];
[request setPostBody:myRequestData];
[[UIApplication sharedApplication]setNetworkActivityIndicatorVisible:YES];
request.delegate = self;
self.conn = request;
[self.conn startAsynchronous];
}
- (void)request:(ASIHTTPRequest *)request didReceiveData:(NSData *)data
{
[_dtReviceData appendData:data];
}
- (void)request:(ASIHTTPRequest *)request didReceiveResponseHeaders:(NSDictionary *)responseHeaders
{
_dtReviceData = [[NSMutableData alloc]init];
}
- (void)requestFinished:(ASIHTTPRequest *)request // 根据request.responseData来获取数据
{
NSDictionary *dicRespon = nil;
NSError *error;
_dtReviceData = [NSMutableData dataWithData:request.responseData];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
dicRespon = [NSJSONSerialization JSONObjectWithData:_dtReviceData options:NSJSONReadingMutableLeaves error:&error];
NSString *str = [dicRespon descriptionWithLocale:dicRespon];
NSLog(@"接口返回:%@",str);
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
ASIResultCode theResultCode = ASIRS_Error;
if (dicRespon && [[dicRespon allKeys] containsObject:@"result"]) {
theResultCode = ASIRS_Success;
}
int result = [[dicRespon objectForKey:@"result"] intValue];
NSString *msg = [dicRespon objectForKey:@"msg"];
if([self validateString:msg] == NO)
{
msg = @"请求失败";
}
if (result == 500) // MARK: 账号异地二次登录
{
}
else
{
if ([self.delegate respondsToSelector:@selector(resultWithDic:urlTag:isSuccess:Result:Message:failImage:)])
{
[self.delegate resultWithDic:dicRespon urlTag:self.urlTag isSuccess:theResultCode Result:result Message:msg failImage:FailStatus];
}
}
}
- (void)requestFailed:(ASIHTTPRequest *)request
{
[[UIApplication sharedApplication]setNetworkActivityIndicatorVisible:NO];
ASIResultCode theResultCode = ASIRS_Error;
if ([self.delegate respondsToSelector:@selector(resultWithDic:urlTag:isSuccess:Result:Message:failImage:)])
{
[self.delegate resultWithDic:nil urlTag:self.urlTag isSuccess:theResultCode Result:0 Message:@"请求失败" failImage:FailStatus];
}
}
- (void)stopConnection
{
[[UIApplication sharedApplication]setNetworkActivityIndicatorVisible:NO];
[self.conn clearDelegatesAndCancel];
}
- (void)dealloc
{
if (self.delegate)
{
self.delegate = nil;
}
}
#pragma mark - 判断字符串是否为空
- (BOOL) validateString:(NSString *) str
{
if(str.length == 0 || [str isKindOfClass:[NSNull class]] || str == nil || str == NULL || [str isEqualToString:@"(null)"] || [[str stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] length]==0 || [str isEqualToString:@"null"])
{
return NO;
}
return YES;
}
@end
3、EVNASIConnectionUtil使用
#import "EVNConnectionUtil.h"
@interface GetTokenFailViewController : BaseViewController<ASIHTTPConnectionDelegate>
{
EVNASIConnectionUtil *conn;
}
......
// 使用
- (void) getTokenMethod
{
conn = [[EVNASIConnectionUtil alloc] initWithURLTag:ASIURLGetTokenTag delegate:self];
NSString *urlString = [NSString stringWithFormat:@"%@%@",URL_HOST,@"getToken.html"];
[conn getResultFromUrlString:urlString postBody:nil postArg:nil method:EVNPOST failImage:0]; // 发起请求
}
- (void) resultWithDic:(NSDictionary *)dicRespon evnUrlTag:(ASIURLTag)URLTag isSuccess:(ASIResultCode)theResultCode Result:(int)res Message:(NSString *)message failImage:(int)failStatus
{
if(URLTag == ASIURLGetTokenTag)
{
if(res == 1)
{
AppDelegate *appDel = (AppDelegate *)[UIApplication sharedApplication].delegate;
appDel.appToken = [NSString stringWithFormat:@"%@",[dicRespon objectForKey:@"token"]];
}
else
{
[NSThread sleepForTimeInterval:0.5];
[self getTokenMethod];
}
}
}
二、AFNetworking再封装
1、AFNetworking异步请求及AFNetworking简析
为了迎合苹果API,AFNetworking3.0中删除了对NSURLConnection的支持,转而对NSURLSession封装使用。
(1)创建网络请求,设置接受数据类型
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.requestSerializer.timeoutInterval = 10;
manager.requestSerializer = [AFHTTPRequestSerializer serializer];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
(2)统一为请求添加head,如:Date 提供日期和时间标志、Content-Length请求内容的长度、Content-Type请求与实体对应的MIME信息等;或者添加自定义header的类型,比如特定用户标记信息,加密信息token等。
[manager.requestSerializer setValue:tokenDes forHTTPHeaderField:@"token"];
......
(3)发起网络请求,GET、POST
GET方式
[self.manager GET:strUrl parameters:strPostBody progress:^(NSProgress * _Nonnull downloadProgress) {
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSLog(@"JSON: %@", responseObject);
[[UIApplication sharedApplication]setNetworkActivityIndicatorVisible:NO];
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"Error: %@", error);
}];
POST方式
[self.manager POST:strUrl parameters:strPostBody progress:^(NSProgress * _Nonnull uploadProgress) {
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSLog(@"JSON: %@", responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"Error: %@", error);
}];
2、EVNAFNConnectionUtil工具类实现
EVNAFNConnectionUtil.h
//
// EVNAFNConnectionUtil.h
// MMBao_master
//
// Created by developer on 16/8/24.
// Copyright © 2016年 仁伯安. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "AFNetworking.h"
#pragma mark - 请求方法
typedef NS_ENUM(NSUInteger, URLMethod)
{
POST = 1,
GET = 2,
};
#pragma mark - TAG定义,命名规则: URL开头+模块名字+Tag
typedef NS_ENUM(NSUInteger, URLTag)
{
#pragma mark: 账户管理
URLGetTokenTag,
#pragma mark - 登录及注册
#pragma mark: 三方登录
};
#pragma mark - 返回的Result
typedef NS_ENUM(NSUInteger, ResultCode)
{
RS_Success = 1,
RS_Error,
};
@protocol AFNConnectionDelegate <NSObject>
@optional
@required
/**
* 网络请求完成(包括数据返回成功、失败、接口超时)后的回调方法
*
* @param dicRespon 网络请求后返回的JSON数据
* @param URLTag 网络请求的标识tag
* @param theResultCode 状态码,成功 && 失败
* @param res 网络请求返回的result,一般1表示请求成功,0表示请求失败
* @param message 提示信息
* @param failStatus 是否显示网络请求异常图片
*/
- (void)resultWithDic:(NSDictionary *)dicRespon urlTag:(URLTag)URLTag isSuccess:(ResultCode)theResultCode Result:(int) res Message:(NSString *) message failImage:(int) failStatus;
@optional
- (void) resultWithString:(NSString *) str;
@end
#pragma mark - EVNAFNConnectionUtil工具类
@interface EVNAFNConnectionUtil : NSObject<AFNConnectionDelegate>
{
NSMutableData *_dtReviceData;
int FailStatus;
}
@property (nonatomic, assign) id<AFNConnectionDelegate> delegate;
@property (nonatomic, assign) URLTag urlTag;
@property (nonatomic, strong) AFHTTPSessionManager *manager;
/**
* 网络请求初始化方法
*
* @param theUrlTag 网络请求的标识tag
* @param theDelegate 网络请求代理
*
* @return ASIHTTP实例
*/
- (instancetype)initWithURLTag:(URLTag)theUrlTag delegate:(id<AFNConnectionDelegate>)theDelegate;
/**
* common 网络请求
*
* @param strUrl URL服务器地址
* @param strPostBody body
* @param theMethod 网络请求方式,比如GET、POST
*/
- (void)getResultFromUrlString:(NSString *)strUrl postBody:(NSString *)strPostBody method:(URLMethod)theMethod;
/**
* 上传图片音频 网络请求
*
* @param strUrl URL服务器地址
* @param dicText 需要的参数,dicImage表示,strImageFileName表示
* @param dicImage 图片名字
* @param strImageFileName 服务器端文件的目录名
* @param avFile 音频类网络请求文件名
*/
- (void)getResultFromUrlString:(NSString *)strUrl dicText:(NSDictionary *)dicText dicImage:(NSDictionary *)dicImage imageFilename:(NSMutableArray *)strImageFileName WithAVFile:(NSString *) avFile;
/**
* 网络请求结束,终止
*/
- (void)stopConnection;
#pragma mark -
- (void)getResultFromUrlString:(NSString *)strUrl postBody:(NSMutableArray *)strPostBodyArray postArg:(NSMutableArray *) argArray method:(URLMethod)theMethod failImage:(int) faileSatatus;
@end
EVNAFNConnectionUtil.m
//
// EVNAFNConnectionUtil.m
// MMBao_master
//
// Created by developer on 16/8/24.
// Copyright © 2016年 仁伯安. All rights reserved.
//
#import "EVNAFNConnectionUtil.h"
#import "AppDelegate.h"
#import "MCdes.h"
#import <AVFoundation/AVFoundation.h>
#define KEYPassWordMCdes @"加密字符"
@implementation EVNAFNConnectionUtil
{
AppDelegate *appDel;
NSString *tokenDes;
}
- (instancetype)initWithURLTag:(URLTag)theUrlTag delegate:(id<AFNConnectionDelegate>) theDelegate
{
self = [super init];
if (self)
{
self.delegate = theDelegate;
self.urlTag = theUrlTag;
appDel = (AppDelegate *)[UIApplication sharedApplication].delegate;
tokenDes = appDel.appToken;
if([self validateString:tokenDes] == NO)
{
tokenDes = @"";
}
}
return self;
}
// URL编码
- (NSString *)encodeToPercentEscapeString: (NSString *) input
{
NSString *outputStr = (NSString *) CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)input, NULL, (CFStringRef)@"!*'();:@=+$,/?%#[]", kCFStringEncodingUTF8));
return outputStr;
}
- (void)getResultFromUrlString:(NSString *)strUrl postBody:(NSMutableArray *)strPostBodyArray postArg:(NSMutableArray *)argArray method:(URLMethod)theMethod failImage:(int)faileSatatus
{
FailStatus = faileSatatus;
strUrl = [strUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSMutableString *strPostBody = [[NSMutableString alloc] initWithString:@""];
for(NSInteger i=0;i<argArray.count;i++)
{
NSString *bodyStr = [[strPostBodyArray objectAtIndex:i] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *argStr = [self encodeToPercentEscapeString:[NSString stringWithFormat:@"%@",[argArray objectAtIndex:i]]];
NSString *s = [NSString stringWithFormat:@"%@%@",bodyStr,argStr];
[strPostBody appendString:s];
}
NSString *urlStr;
if([self validateString:strPostBody] == NO)
{
urlStr = [NSString stringWithFormat:@"%@",strUrl];
}
else
{
urlStr = [NSString stringWithFormat:@"%@%@",strUrl,strPostBody];
}
NSLog(@"请求接口:%@",urlStr);
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.requestSerializer.timeoutInterval = 10;
manager.requestSerializer = [AFHTTPRequestSerializer serializer];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
//设置传送类型
NSString *contentType = [NSString stringWithFormat:@"application/x-www-form-urlencoded"];
//给传输类型添加内容
[manager.requestSerializer setValue:contentType forHTTPHeaderField:@"Content-Type"];
#pragma mark - 修改header头
NSString *dataDes = [MCdes encryptUseDES:@"需要加密的字符" key:KEYPassWordMCdes];
[manager.requestSerializer setValue: dataDes forHTTPHeaderField:@"User-Agent"];
[manager.requestSerializer setValue:tokenDes forHTTPHeaderField:@"token"];
[manager.requestSerializer setValue:@"应用缩写_iOS" forHTTPHeaderField:@"phone_type"];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/html",@"text/json",@"text/javascript", @"text/plain", nil];
self.manager = manager;
[[UIApplication sharedApplication]setNetworkActivityIndicatorVisible:YES];
if (theMethod == GET)
{
[self.manager GET:strUrl parameters:strPostBody progress:^(NSProgress * _Nonnull downloadProgress) {
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSLog(@"JSON: %@", responseObject);
[[UIApplication sharedApplication]setNetworkActivityIndicatorVisible:NO];
NSError *error;
NSDictionary *dicRespon = responseObject;
NSString *str = [dicRespon descriptionWithLocale:dicRespon];
NSLog(@"接口返回:%@",str);
ResultCode theResultCode = RS_Error;
if (dicRespon && [[dicRespon allKeys] containsObject:@"result"])
{
theResultCode = RS_Success;
}
int result = [[dicRespon objectForKey:@"result"] intValue];
NSString *msg = [dicRespon objectForKey:@"msg"];
if([self validateString:msg] == NO)
{
msg = @"请求失败";
}
if (result == 500) // MARK: 账号异地二次登录
{
}
else
{
if ([self.delegate respondsToSelector:@selector(resultWithDic:urlTag:isSuccess:Result:Message:failImage:)])
{
[self.delegate resultWithDic:dicRespon urlTag:self.urlTag isSuccess:theResultCode Result:result Message:msg failImage:FailStatus];
}
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"Error: %@", error);
[[UIApplication sharedApplication]setNetworkActivityIndicatorVisible:NO];
ResultCode theResultCode = RS_Error;
if ([self.delegate respondsToSelector:@selector(resultWithDic:urlTag:isSuccess:Result:Message:failImage:)])
{
[self.delegate resultWithDic:nil urlTag:self.urlTag isSuccess:theResultCode Result:0 Message:@"请求失败" failImage:FailStatus];
}
}];
}
else
{
[self.manager POST:strUrl parameters:strPostBody progress:^(NSProgress * _Nonnull uploadProgress) {
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSLog(@"JSON: %@", responseObject);
[[UIApplication sharedApplication]setNetworkActivityIndicatorVisible:NO];
NSError *error;
NSDictionary *dicRespon = responseObject;
NSString *str = [dicRespon descriptionWithLocale:dicRespon];
NSLog(@"接口返回:%@",str);
ResultCode theResultCode = RS_Error;
if (dicRespon && [[dicRespon allKeys] containsObject:@"result"])
{
theResultCode = RS_Success;
}
int result = [[dicRespon objectForKey:@"result"] intValue];
NSString *msg = [dicRespon objectForKey:@"msg"];
if([self validateString:msg] == NO)
{
msg = @"请求失败";
}
if (result == 500) // MARK: 账号异地二次登录
{
}
else
{
if ([self.delegate respondsToSelector:@selector(resultWithDic:urlTag:isSuccess:Result:Message:failImage:)])
{
[self.delegate resultWithDic:dicRespon urlTag:self.urlTag isSuccess:theResultCode Result:result Message:msg failImage:FailStatus];
}
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"Error: %@", error);
[[UIApplication sharedApplication]setNetworkActivityIndicatorVisible:NO];
ResultCode theResultCode = RS_Error;
if ([self.delegate respondsToSelector:@selector(resultWithDic:urlTag:isSuccess:Result:Message:failImage:)])
{
[self.delegate resultWithDic:nil urlTag:self.urlTag isSuccess:theResultCode Result:0 Message:@"请求失败" failImage:FailStatus];
}
}];
}
}
#pragma mark - 异步请求数据,strUrl表示域名,strPostBody表示上传的参数,theMethod表示请求方式
- (void)getResultFromUrlString:(NSString *)strUrl postBody:(NSString *)strPostBody method:(URLMethod)theMethod
{
strUrl = [strUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
strPostBody = [strPostBody stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *urlStr;
if([self validateString:strPostBody] == NO)
{
urlStr = [NSString stringWithFormat:@"%@",strUrl];
}
else
{
urlStr = [NSString stringWithFormat:@"%@%@",strUrl,strPostBody];
}
NSLog(@"请求接口:%@",urlStr);
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.requestSerializer.timeoutInterval = 10;
manager.requestSerializer = [AFHTTPRequestSerializer serializer];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
//设置传送类型
NSString *contentType = [NSString stringWithFormat:@"application/x-www-form-urlencoded"];
//给传输类型添加内容
[manager.requestSerializer setValue:contentType forHTTPHeaderField:@"Content-Type"];
#pragma mark - 修改header头
NSString * dataDes = [MCdes encryptUseDES:@"需要加密的字符" key:KEYPassWordMCdes];
[manager.requestSerializer setValue: dataDes forHTTPHeaderField:@"User-Agent"];
[manager.requestSerializer setValue:tokenDes forHTTPHeaderField:@"token"];
[manager.requestSerializer setValue:@"应用缩写_iOS" forHTTPHeaderField:@"phone_type"];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/html",@"text/json",@"text/javascript", @"text/plain", nil];
self.manager = manager;
[[UIApplication sharedApplication]setNetworkActivityIndicatorVisible:YES];
if (theMethod == GET)
{
[self.manager GET:strUrl parameters:strPostBody progress:^(NSProgress * _Nonnull downloadProgress) {
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSLog(@"JSON: %@", responseObject);
[[UIApplication sharedApplication]setNetworkActivityIndicatorVisible:NO];
NSError *error;
NSDictionary *dicRespon = responseObject;
NSString *str = [dicRespon descriptionWithLocale:dicRespon];
NSLog(@"接口返回:%@",str);
ResultCode theResultCode = RS_Error;
if (dicRespon && [[dicRespon allKeys] containsObject:@"result"])
{
theResultCode = RS_Success;
}
int result = [[dicRespon objectForKey:@"result"] intValue];
NSString *msg = [dicRespon objectForKey:@"msg"];
if([self validateString:msg] == NO)
{
msg = @"请求失败";
}
if (result == 500) // MARK: 账号异地二次登录
{
}
else
{
__weak typeof(self) weakSelf = self;
if ([weakSelf.delegate respondsToSelector:@selector(resultWithDic:urlTag:isSuccess:Result:Message:failImage:)])
{
[weakSelf.delegate resultWithDic:dicRespon urlTag:self.urlTag isSuccess:theResultCode Result:result Message:msg failImage:FailStatus];
}
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"Error: %@", error);
[[UIApplication sharedApplication]setNetworkActivityIndicatorVisible:NO];
ResultCode theResultCode = RS_Error;
__weak typeof(self) weakSelf = self;
if ([weakSelf.delegate respondsToSelector:@selector(resultWithDic:urlTag:isSuccess:Result:Message:failImage:)])
{
[weakSelf.delegate resultWithDic:nil urlTag:self.urlTag isSuccess:theResultCode Result:0 Message:@"请求失败" failImage:FailStatus];
}
}];
}
else
{
[self.manager POST:strUrl parameters:strPostBody progress:^(NSProgress * _Nonnull uploadProgress) {
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSLog(@"JSON: %@", responseObject);
[[UIApplication sharedApplication]setNetworkActivityIndicatorVisible:NO];
NSError *error;
NSDictionary *dicRespon = responseObject;
NSString *str = [dicRespon descriptionWithLocale:dicRespon];
NSLog(@"接口返回:%@",str);
ResultCode theResultCode = RS_Error;
if (dicRespon && [[dicRespon allKeys] containsObject:@"result"]) {
theResultCode = RS_Success;
}
int result = [[dicRespon objectForKey:@"result"] intValue];
NSString *msg = [dicRespon objectForKey:@"msg"];
if([self validateString:msg] == NO)
{
msg = @"请求失败";
}
if (result == 500) // MARK: 账号异地二次登录
{
}
else
{
__weak typeof(self) weakSelf = self;
if ([weakSelf.delegate respondsToSelector:@selector(resultWithDic:urlTag:isSuccess:Result:Message:failImage:)])
{
[weakSelf.delegate resultWithDic:dicRespon urlTag:self.urlTag isSuccess:theResultCode Result:result Message:msg failImage:FailStatus];
}
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"Error: %@", error);
[[UIApplication sharedApplication]setNetworkActivityIndicatorVisible:NO];
ResultCode theResultCode = RS_Error;
__weak typeof(self) weakSelf = self;
if ([weakSelf.delegate respondsToSelector:@selector(resultWithDic:urlTag:isSuccess:Result:Message:failImage:)])
{
[weakSelf.delegate resultWithDic:nil urlTag:self.urlTag isSuccess:theResultCode Result:0 Message:@"请求失败" failImage:FailStatus];
}
}];
}
}
......
- (void)stopConnection
{
[[UIApplication sharedApplication]setNetworkActivityIndicatorVisible:NO];
[self.manager invalidateSessionCancelingTasks:YES];
}
- (void)dealloc
{
if (self.delegate)
{
self.delegate = nil;
}
}
#pragma mark - 判断字符串是否为空
- (BOOL) validateString:(NSString *) str
{
if(str.length == 0 || [str isKindOfClass:[NSNull class]] || str == nil || str == NULL || [str isEqualToString:@"(null)"] || [[str stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] length]==0 || [str isEqualToString:@"null"])
{
return NO;
}
return YES;
}
@end
3、EVNAFNConnectionUtil使用
@interface GetTokenFailViewController : BaseViewController<AFNConnectionDelegate>
{
EVNAFNConnectionUtil *conn;
}
......
- (void) getTokenMethod
{
conn = [[EVNAFNConnectionUtil alloc] initWithURLTag:URLGetTokenTag delegate:self];
NSString *urlString = [NSString stringWithFormat:@"%@%@",URL_HOST_CHEN,@"token/getToken.html"];
[conn getResultFromUrlString:urlString postBody:nil postArg:nil method:EVNPOST failImage:0];
}
- (void) resultWithDic:(NSDictionary *)dicRespon evnUrlTag:(EVNURLTag)URLTag isSuccess:(EVNResultCode)theResultCode Result:(int)res Message:(NSString *)message failImage:(int)failStatus
{
if(URLTag == URLGetTokenTag)
{
if(res == 1)
{
AppDelegate *appDel = (AppDelegate *)[UIApplication sharedApplication].delegate;
appDel.appToken = [NSString stringWithFormat:@"%@",[dicRespon objectForKey:@"token"]];
}
else
{
[NSThread sleepForTimeInterval:0.5];
[self getTokenMethod];
}
}
}
三、补充
时间仓促,不足之处见谅。。。。。。
本文已在版权印备案,如需转载请在版权印获取授权。
获取版权