和线上app用户反馈及在用测试工具开发测试中的反应情况,最后得出结论AFNetworking的优点相对ASIHttpReqeuest的优点大一些,尤其在网络稳定性方面。处理crash这些情况,下面通过两者详细的优缺点比较了解 一下,为什么把ASIHttpRequest给替换成了ASNetworking。
二、AFNetworking的优缺点
优点:
维护和使用者相对多
对ARC的支持
对Block使用的支持非常好
维护和使用者相对多(目前已到2.4.1版)
专门对异步请求的支持
支持基于url缓存的支持
图片及NSURLCache、AFCache缓存实用
支持后台下载,缓存离线请求的支持(SDURLCache)
对JSON支持好
对实现的http请求比较容易
对https的支持
缺点:
是基于Foundation框架的NSURLConnection对网络进行的封装不是用的低层的
CFNetwork进行的封装扩展的功能目前相对少一些,但在Http上的网络支持已足够
ASIHttpRequest:
优点:
对网络底层CFNetwork支持,在性能上占优
对代理proxy支持设置比较方便
支持离线下载和基于url的缓存
对https的支持
对实现的http请求方面实现的不是太好,会多写点代码
支持异步和同步的支持
缺点:
在2012年社区已停止更新
对目前最新版本IOS7和8上使用时会有些问题,特别是网络异步请求多时,多线程使用时经常出现时容易出现网络不稳定的问题。
对ARC支持不好,不支持苹果推荐给我们使用的ARC性能
对Block不够好,框架代码在多线程方面用的不好
ASI框架在面向对象方面不够抽象
接口和实现代码看着过于庞大,里面过程化的实现比较严重不利于扩展和维护
三、在代码实现仅用GET请求来做一下AFNetworking和ASIHttpRequest的比较:
/** * AFNetworking初始化HTTP */ - (void)httpInit { //应用配置文件 self.manager = [AFHTTPRequestOperationManager manager]; //申明返回的结果是JSON类型 self.manager.responseSerializer = [AFJSONResponseSerializer serializer]; //如果报接受类型不一致请替换一致text/html self.manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"text/html"]; //清求时间设置 self.manager.requestSerializer.timeoutInterval = 30; //设置代理 //[self setProxy]; //添加header头信息 [self addRequestHeader]; } /** * AFNetworking发送get请求 */ - (void)startGet:(NSString*)uri tag:(NSInteger)tag { [self httpInit]; [self.manager GET:[NSString stringWithFormat:@"%@%@",self.baseUrl,uri] parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { [self requestFinished:responseObject tag:tag]; } failure:^(AFHTTPRequestOperation *operation, NSError *error) { [self requestFailed:tag]; }]; } /** * ASIHttpRequest初始化HTTP */ -(void)httpInit:(NSString *)method uri:(NSString *)uri { //应用配置文件 [self setRes:[ASIFormDataRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@%@",self.baseUrl,uri]]]]; //设置代理 if (self.host != nil) { [self.res setProxyHost:self.host]; } if (self.port > 0) { [self.res setProxyPort:self.port]; } //设置代理 [self.res setDelegate:self]; //设置允许记录cookie [self.res setUseCookiePersistence:YES]; //超时设置 [self.res setTimeOutSeconds:30]; //请求方式 [self.res setRequestMethod:method]; } /** * ASIHttpRequest发送get请求 */ - (void)startGet:(NSString*)uri tag:(NSInteger)tag{ [self cancel];//取消前一个请求 [self httpInit:@"GET" uri:uri]; [self.res setTag:tag]; [self.res startAsynchronous]; }
四、AFNetworking在Model层对app的网络请求的封装实现过的代码:
initData.h
// // InitData.h // // Created by ligangming on 14-1-2. // Copyright (c) 2014年 ligangming. All rights reserved. // #define DEFAULT_PAGESIZE 20 //默认分页数量 /** 请求完成处理 */ typedef void (^Complete)(); /** 请求失败处理 */ typedef void (^Failed)(NSString *state,NSString *errmsg); /** 数据请求模型的基类,包含基本网络请求 */ @interface InitData : NSObject{ @protected Complete _complete; //请求完成 Failed _failed; //请求失败 } //HTTP参数设置 @property(nonatomic,strong)NSString *baseUrl; //API基础地址 @property(nonatomic,strong)NSString *host; //代理主机IP地址 @property(nonatomic,assign)NSInteger port; //代理主机端口 @property(nonatomic,strong)NSString *errCode; //错误代码 @property(nonatomic,strong)NSString *errMsg; //错误描述 @property(nonatomic,strong)NSString *version; //协议版本(客户端兼容最小版本) - (id)initWithDelegate:(id)delegate; /** * 发送get请求 */ - (void)startGet:(NSString*)url tag:(NSInteger)tag; /** * 发送getCache请求 */ - (void)startCache:(NSString *)aCacheName cacheTime:(NSInteger)aTime uri:(NSString *)uri tag:(NSInteger)tag; /** * 发送post请求 */ - (void)startPost:(NSString*)url params:(NSDictionary*)params tag:(NSInteger)tag; /** * 上传文件 */ - (void)uploadFileURI:(NSString*)aUri filePath:(NSString*)aPath keyName:(NSString *)aKeyName; /** * 取消请求 */ - (void)cancel; @end #pragma mark delegate @protocol InitDataDelegate <NSObject> @optional /** 请求完成时-调用 */ -(void)getFinished:(NSDictionary *)msg tag:(NSInteger)tag; /** 请求失败时-调用 */ -(void)getError:(NSDictionary *)msg tag:(NSInteger)tag; @end
// // InitData.m // // Created by ligangming on 14-1-2. // Copyright (c) 2014年 ligangming. All rights reserved. // #import "InitData.h" #import "AFNetworking.h" Class object_getClass(id object); @interface InitData() { Class afOrinClass; } @property(nonatomic,strong)AFHTTPRequestOperationManager *manager; //AF请求对象 @property(nonatomic,weak)id<InitDataDelegate> delegate; @end @implementation InitData #pragma mark initData - (id)initWithDelegate:(id)delegate { if ((self = [super init])) { afOrinClass = object_getClass(delegate); [self setDelegate:delegate]; [self setDefault]; } return self; } /** * 初始化设置 */ - (void)setDefault { //载入系统配置 NSDictionary *cfgDic = [NSObject JzbGetConfig]; //API地址 [self setBaseUrl:[cfgDic objectForKey:@"apiUrl"]]; //代理HOST if (![[cfgDic objectForKey:@"apiHost"] isEqualToString:@""]) { [self setHost:[cfgDic objectForKey:@"apiHost"]]; //重置API地址(测试用) [self setBaseUrl:[NSString stringWithFormat:@"http://%@", self.host]]; }else{ [self setHost:nil]; } //代理port [self setPort:[[cfgDic objectForKey:@"apiPort"] intValue]]; } #pragma mark httpMode /** * 初始化HTTP */ - (void)httpInit { //应用配置文件 self.manager = [AFHTTPRequestOperationManager manager]; //申明返回的结果是JSON类型 self.manager.responseSerializer = [AFJSONResponseSerializer serializer]; //如果报接受类型不一致请替换一致text/html self.manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"text/html"]; //清求时间设置 self.manager.requestSerializer.timeoutInterval = 30; //设置代理 //[self setProxy]; //添加header头信息 [self addRequestHeader]; } /** * 添加header头信息 */ - (void)addRequestHeader { //当前应用版块号 //应用类型IOS //当前应用 [self.manager.requestSerializer setValue:@"xxx" forHTTPHeaderField:@"TOKEN"]; } /** * 发送get请求 */ - (void)startGet:(NSString*)uri tag:(NSInteger)tag { [self httpInit]; [self.manager GET:[NSString stringWithFormat:@"%@%@",self.baseUrl,uri] parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { [self requestFinished:responseObject tag:tag]; } failure:^(AFHTTPRequestOperation *operation, NSError *error) { [self requestFailed:tag]; }]; } - (AFHTTPRequestOperation *)cacheOperationWithRequest:(NSURLRequest *)urlRequest tag:(NSInteger)tag success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure { AFHTTPRequestOperation *operation = [self.manager HTTPRequestOperationWithRequest:urlRequest success:^(AFHTTPRequestOperation *operation, id responseObject){ NSCachedURLResponse *cachedURLResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:urlRequest]; cachedURLResponse = [[NSCachedURLResponse alloc] initWithResponse:operation.response data:operation.responseData userInfo:nil storagePolicy:NSURLCacheStorageAllowed]; [[NSURLCache sharedURLCache] storeCachedResponse:cachedURLResponse forRequest:urlRequest]; success(operation,responseObject); }failure:^(AFHTTPRequestOperation *operation, NSError *error) { if (error.code == kCFURLErrorNotConnectedToInternet) { NSCachedURLResponse *cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:urlRequest]; if (cachedResponse != nil && [[cachedResponse data] length] > 0) { success(operation, cachedResponse.data); } else { failure(operation, error); } } else { failure(operation, error); } }]; return operation; } /** * 发送getCache请求 */ - (void)startCache:(NSString *)aCacheName cacheTime:(NSInteger)aTime uri:(NSString *)uri tag:(NSInteger)tag { [self httpInit]; AFHTTPRequestSerializer *serializer = [AFHTTPRequestSerializer serializer]; NSMutableURLRequest *request = [serializer requestWithMethod:@"GET" URLString:[NSString stringWithFormat:@"%@%@",self.baseUrl,uri] parameters:nil error:nil]; [request setTimeoutInterval:20]; [request setCachePolicy:NSURLRequestUseProtocolCachePolicy]; //此处将NSURLRequestReturnCacheDataElseLoad替换要不然无论有无网络情况每次请求都会取本地缓存数据 //请求成功Block块 void (^requestSuccessBlock)(AFHTTPRequestOperation *operation, id responseObject) = ^(AFHTTPRequestOperation *operation, id responseObject) { [self requestFinished:responseObject tag:tag]; }; //请求失败Block块 void (^requestFailureBlock)(AFHTTPRequestOperation *operation, NSError *error) = ^(AFHTTPRequestOperation *operation, NSError *error){ [self requestFailed:tag]; }; //请求数据 AFHTTPRequestOperation *operation = [self cacheOperationWithRequest:request tag:tag success:requestSuccessBlock failure:requestFailureBlock]; [self.manager.operationQueue addOperation:operation]; } /** * 获取缓存数据 */ - (id)cachedResponseObject:(AFHTTPRequestOperation *)operation{ NSCachedURLResponse* cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:operation.request]; AFHTTPResponseSerializer* serializer = [AFJSONResponseSerializer serializer]; id responseObject = [serializer responseObjectForResponse:cachedResponse.response data:cachedResponse.data error:nil]; return responseObject; } /** * 发送post请求 */ - (void)startPost:(NSString*)uri params:(NSDictionary*)params tag:(NSInteger)tag { [self httpInit]; [self.manager POST:[NSString stringWithFormat:@"%@%@",self.baseUrl,uri] parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) { [self requestFinished:responseObject tag:tag]; } failure:^(AFHTTPRequestOperation *operation, NSError *error) { [self requestFailed:tag]; }]; } /** * 上传文件 */ - (void)uploadFileURI:(NSString *)aUri filePath:(NSString *)aPath keyName:(NSString *)aKeyName { [self httpInit]; [self.manager POST:[NSString stringWithFormat:@"%@%@",self.baseUrl,aUri] parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) { NSData *imageData = [[NSData alloc] initWithContentsOfFile:aPath]; //获取文件类型 NSMutableString *filePath = [NSMutableString stringWithString:aPath]; CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)[filePath pathExtension], NULL); CFStringRef MIMEType = UTTypeCopyPreferredTagWithClass (UTI, kUTTagClassMIMEType); NSString *fileName = [filePath lastPathComponent]; //将得到的二进制图片拼接到表单中 /** data,指定上传的二进制流;name,服务器端所需参数名;fileName,指定文件名;mimeType,指定文件格式 */ [formData appendPartWithFileData:imageData name:aKeyName fileName:fileName mimeType:(__bridge NSString *)(MIMEType)]; }success:^(AFHTTPRequestOperation *operation, id responseObject){ [self requestFinished:responseObject tag:200]; }failure:^(AFHTTPRequestOperation *operation, NSError *error) { }]; /* /设置上传操作的进度 [operation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) { NSLog(@"Sent %lld of %lld bytes", totalBytesWritten, totalBytesExpectedToWrite); }]; UIProgressView *progress = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault]; [progress setProgressWithUploadProgressOfOperation:operation animated:YES]; [progress setFrame:CGRectMake(0, 130, 320, 30)]; [self.view addSubview:progress]; */ //[operation start]; } /** 停止请求 */ - (void)cancel { if (_manager != nil) { _manager = nil; } } /** * 清理回调block */ - (void)cleanupBlocks { _complete = nil; _failed = nil; } /* 解析通用协议头: 1.检查协议体合法性 2.协议版本检查,执行协议版本客户端处理逻辑 返回值:BOOL 通过解析检查返回YES,否则 NO 对于没有通过检查的协议消息,返回客户端协议错误的消息,或者版本不支持的错误 */ - (BOOL)parseHead:(NSDictionary*)msg { //错误代码解析 //错误描述 //版本提取,客户端版本规则逻辑执行 return YES; } #pragma mark AFHTTPDelegate /** * 代理-请求结束 */ - (void)requestFinished:(NSDictionary *)aDictionary tag:(NSInteger)aTag { //如果消息头解析成功并通过合法性检查 if([self parseHead:aDictionary] == YES){ if ([self.errCode intValue] <= 0) { if ([self.delegate respondsToSelector:@selector(getFinished:tag:)]) { [self.delegate getFinished:aDictionary tag:aTag]; } }else{ if (_failed) { _failed(self.errCode,self.errMsg); } if ([self.delegate respondsToSelector:@selector(getError:tag:)]) { [self.delegate getError:aDictionary tag:aTag]; } } } } /** * 代理-请求失败 */ - (void)requestFailed:(NSInteger)aTag { if (afOrinClass != object_getClass(_delegate)) { NSLog(@"model已销毁"); return; } if (_failed) { _failed(@"1",@"request error"); } //检测如果有配置代理则去执行代理 if ([self.delegate respondsToSelector:@selector(getError:tag:)]) { NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:@"1",@"errcode",@"request error",@"errmsg", nil]; [self.delegate getError:dic tag:aTag]; } } @end