iOS网络通信类库用AFNetworking替换ASHttpRequest的解决方案

来源:互联网 发布:订阅 sql server 时间 编辑:程序博客网 时间:2024/06/03 14:50
一、AFNetworking替换ASHttpRequest原因
经过近两年开发IOS使用AFNetworking和ASIHttpRequest的经验,结合在实际开发App的遇到网络问题

和线上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

////  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


         

0 0
原创粉丝点击