博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ASIHttpRequest封装
阅读量:7020 次
发布时间:2019-06-28

本文共 14056 字,大约阅读时间需要 46 分钟。

ASIHttpRequest是一个非常好的库,只是直接使用稍嫌麻烦,以下就尝试来封装一下吧。

思路:每次请求时,须要创建一个ASIHttpRequest对象,设置它的属性(url,delegate。postValue,requestMethod等)之后就可以開始异步请求。所以我们能够创建一个类。对外提供一个请求方法,结构例如以下:

@interface RequestService : NSObject+ (void)requestWithUrlString:(NSString *)urlString                      params:(NSDictionary *)params                  httpMethod:(NSString *)httpMethod                    delegate:(id)delegate;@end

使用例如以下:

[RequestService requestWithUrlString:urlString                                  params:params                              httpMethod:httpMethod                                delegate:delegate];
看起来非常easy嘛,这样即可了吗?

考虑一个问题,此时传入的delegate是请发起请求的对象。假设我们想要对请求返回做统一的处理,就无法做到了。为了实现这一目的,能够将ASIHttpRequest的delegate设置成RequestService实例对象,请求返回昨晚处理后再将处理结果通知给发起请求的对象。

那么RequestService请求的方法就须要改成实例方法。

改动后代码例如以下:

@protocol RequestServiceDelegate 
- (void)requestWillBegin;- (void)requestDidSucceedWithData:(id)data;- (void)requestDidFailWithError:(NSError *)error;@end@interface RequestService : NSObject@property (nonatomic,assign)id
delegate;- (void)requestWithUrlString:(NSString *)urlString params:(NSDictionary *)params httpMethod:(NSString *)httpMethod;@end
注意除了将类方法改动成实例方法之外,我们去掉了方法传參ASIHttpRequestDelegate,同一时候给它加了自己的delegate属性。用于在请求返回处理完毕后通知发起请求的对象。

使用例如以下:

RequestService *request = [[RequestService alloc] init];    request.delegate = self;    [request requestWithUrlString:urlString                           params:params                       httpMethod:httpMethod];
在这里须要特别注意创建的request对象的生命周期,由于ASIHttpRequest运行的是异步请求,当请求完毕,通知request对象时。假设request对象已经销毁,那么代码就会报错。因此使用时,须要发起请求的对象持有此request。并在请求完毕后释放它。

让每一个对象管理请求,听起来就非常麻烦,又违背了想要统一管理的初衷,那么应该怎么办呢?

让我们来使用单例吧!

创建一个单例对象HttpClient。它有一个属性requestItems。

每次发起请求时,将请求的Item存入该属性。

请求结束后移除Item。

对外,它要提供一个request方法,并须要一个属性保存发起请求的对象。

HttpClient的结构例如以下:

@protocol HttpClientDelegate 
- (void)requestDidFinishWithData:(NSDictionary *)data urlString:(NSString *)urlString nTag:(NSInteger)nTag sKey:(NSString *)sKey;- (void)requestDidFailWithError:(NSError *)error urlString:(NSString *)urlString nTag:(NSInteger)nTag sKey:(NSString *)sKey;@end@interface HttpClient : NSObject@property (nonatomic,strong)NSMutableDictionary *items;+ (HttpClient *)sharedClient;- (void)requestWithUrl:(NSString *)urlString params:(NSDictionary *)params httpMethod:(NSString *)httpMethod delegate:(id
)delegate;@end
使用例如以下:
[[HttpClient sharedClient] requestWithUrl:kProductListURL                                       params:params                                   httpMethod:@"GET"                                     delegate:self];
HttpClient内部怎样实现对每次request的管理呢?首先在请求时,创建一个requestItem,调用requestItem的请求方法,然后将其增加requestItems。当requestItem接收到返回时,通知HttpClient,最后由HttpClient通知发起请求的对象,并移除该requestItem。

HttpClient的request方法例如以下:

- (void)requestWithUrl:(NSString *)urlString                      params:(NSDictionary *)params                  httpMethod:(NSString *)httpMethod                    delegate:(id
)delegate{ HttpRequestItem *item = [[HttpRequestItem alloc] init]; item.delegate = delegate; [item requestWithUrlString:urlString params:params httpMethod:httpMethod]; NSUInteger hashValue = [item hash]; [self.items addObject:item];}
用于接收RequestItem的通知方法例如以下:
- (void)didFinishWithItem:(HttpRequestItem *)item                    error:(NSError *)error{    if (error == nil) {        // 请求成功        if (item.delegate && [item.delegate respondsToSelector:@selector(requestDidFinishWithData:urlString:nTag:sKey:)]) {            NSDictionary *data = [NSJSONSerialization JSONObjectWithData:item.httpReq.responseData options:NSJSONReadingMutableContainers error:nil];            [item.delegate requestDidFinishWithData:data urlString:item.urlString nTag:item.nTag sKey:item.sKey];        }    } else {        // 请求出错        if (item.delegate && [item.delegate respondsToSelector:@selector(requestDidFailWithError:urlString:nTag:sKey:)]) {            [item.delegate requestDidFailWithError:error urlString:item.urlString nTag:item.nTag sKey:item.sKey];        }    }        [self removeItem:item];}
HttpRequestItem也就是我们之前的RequestService,它接收ASIHttpRequest的返回的方法例如以下:
#pragma mark - ASIHTTPRequest delegate- (void)requestFinished:(ASIHTTPRequest *)request{    NSError *error = nil;    // doSomething with response here....    if ([[HttpClient sharedClient] respondsToSelector:@selector(didFinishWithItem:error:)]) {        [[HttpClient sharedClient] performSelector:@selector(didFinishWithItem:error:) withObject:self withObject:error];    }}- (void)requestFailed:(ASIHTTPRequest *)request{    if ([[HttpClient sharedClient] respondsToSelector:@selector(didFinishWithItem:error:)]) {        [[HttpClient sharedClient] performSelector:@selector(didFinishWithItem:error:) withObject:self withObject:request.error];    }}
以上,主要的雏形已经出来了~还有哪些能够改进的地方呢?

考虑两个问题:

1.同一个对象,可能会发起多次请求,怎样差别这些请求的返回?

2.假设想主动取消某个正在进行的请求,应该怎么办?

对于问题1,可在请求时传入參数,如tag、key等,由RequestItem保存这些參数,请求完毕后依据这些參数来区分不同的请求。

对于问题2。相应方法是记录每一个RequestItem的HashValue,并对外提供依据HashValue取消相应请求的方法。

完整的代码例如以下:

HttpClient.h

#import 
@protocol HttpClientDelegate
- (void)requestDidFinishWithData:(NSDictionary *)data urlString:(NSString *)urlString nTag:(NSInteger)nTag sKey:(NSString *)sKey;- (void)requestDidFailWithError:(NSError *)error urlString:(NSString *)urlString nTag:(NSInteger)nTag sKey:(NSString *)sKey;@end@interface HttpClient : NSObject@property (nonatomic,strong)NSMutableDictionary *items;+ (HttpClient *)sharedClient;- (NSUInteger)requestWithUrl:(NSString *)urlString params:(NSDictionary *)params httpMethod:(NSString *)httpMethod delegate:(id
)delegate;- (NSUInteger)requestWithUrl:(NSString *)urlString params:(NSDictionary *)params httpMethod:(NSString *)httpMethod delegate:(id
)delegate nTag:(NSInteger)nTag;- (NSUInteger)requestWithUrl:(NSString *)urlString params:(NSDictionary *)params httpMethod:(NSString *)httpMethod delegate:(id
)delegate sKey:(NSString *)sKey;- (NSUInteger)requestWithUrl:(NSString *)urlString params:(NSDictionary *)params httpMethod:(NSString *)httpMethod delegate:(id
)delegate nTag:(NSInteger)nTag sKey:(NSString *)sKey;// 取消请求- (BOOL)cancelRequestWithHashValue:(NSUInteger)hashValue;@end
HttpClient.m
#import "HttpClient.h"#import "HttpRequestItem.h"@implementation HttpClient+ (HttpClient *)sharedClient {    static HttpClient *_sharedClient = nil;    static dispatch_once_t oncePredicate;    dispatch_once(&oncePredicate, ^{        _sharedClient = [[self alloc] init];        _sharedClient.items = [NSMutableDictionary dictionary];    });        return _sharedClient;}- (NSUInteger)requestWithUrl:(NSString *)urlString                      params:(NSDictionary *)params                  httpMethod:(NSString *)httpMethod                    delegate:(id
)delegate{ return [self requestWithUrl:urlString params:params httpMethod:httpMethod delegate:delegate nTag:0 sKey:nil];}- (NSUInteger)requestWithUrl:(NSString *)urlString params:(NSDictionary *)params httpMethod:(NSString *)httpMethod delegate:(id
)delegate nTag:(NSInteger)nTag{ return [self requestWithUrl:urlString params:params httpMethod:httpMethod delegate:delegate nTag:nTag sKey:nil];}- (NSUInteger)requestWithUrl:(NSString *)urlString params:(NSDictionary *)params httpMethod:(NSString *)httpMethod delegate:(id
)delegate sKey:(NSString *)sKey{ return [self requestWithUrl:urlString params:params httpMethod:httpMethod delegate:delegate nTag:0 sKey:sKey];}- (NSUInteger)requestWithUrl:(NSString *)urlString params:(NSDictionary *)params httpMethod:(NSString *)httpMethod delegate:(id
)delegate nTag:(NSInteger)nTag sKey:(NSString *)sKey{ HttpRequestItem *item = [[HttpRequestItem alloc] init]; item.delegate = delegate; item.nTag = nTag; item.sKey = sKey; [item requestWithUrlString:urlString params:params httpMethod:httpMethod]; NSUInteger hashValue = [item hash]; [self.items setObject:item forKey:@(hashValue)]; return hashValue;}- (BOOL)cancelRequestWithHashValue:(NSUInteger)hashValue{ HttpRequestItem *item = [_items objectForKey:@(hashValue)]; if (item) { [item.httpReq clearDelegatesAndCancel]; [_items removeObjectForKey:@(hashValue)]; } return YES;}#pragma mark - actions- (void)removeItem:(HttpRequestItem *)item{ NSUInteger hashValue = [item hash]; id object = [_items objectForKey:@(hashValue)]; if (object != nil) { [[(HttpRequestItem *)object httpReq] clearDelegatesAndCancel]; [_items removeObjectForKey:@(hashValue)]; }}#pragma mark - HttpRequestItem delegate// 请求结束- (void)didFinishWithItem:(HttpRequestItem *)item error:(NSError *)error{ if (error == nil) { // 请求成功 if (item.delegate && [item.delegate respondsToSelector:@selector(requestDidFinishWithData:urlString:nTag:sKey:)]) { NSDictionary *data = [NSJSONSerialization JSONObjectWithData:item.httpReq.responseData options:NSJSONReadingMutableContainers error:nil]; [item.delegate requestDidFinishWithData:data urlString:item.urlString nTag:item.nTag sKey:item.sKey]; } } else { // 请求出错 if (item.delegate && [item.delegate respondsToSelector:@selector(requestDidFailWithError:urlString:nTag:sKey:)]) { [item.delegate requestDidFailWithError:error urlString:item.urlString nTag:item.nTag sKey:item.sKey]; } } [self removeItem:item];}@end
HttpRequestItem.h
#import 
#import "ASIFormDataRequest.h"#import "RequestConstants.h"#import "HttpClient.h"@interface HttpRequestItem : NSObject@property (nonatomic,strong)ASIHTTPRequest *httpReq;@property (nonatomic,copy)NSString *urlString;@property (nonatomic,assign)NSInteger nTag;@property (nonatomic,copy)NSString *sKey;@property (nonatomic,assign)id
delegate;- (void)requestWithUrlString:(NSString *)urlString params:(NSDictionary *)params httpMethod:(NSString *)httpMethod;@end

HttpRequestItem.m

#import "HttpRequestItem.h"NSString * const kHttpBaseURLString = @"http://192.168.33.6:8080/";@implementation HttpRequestItem- (void)requestWithUrlString:(NSString *)urlString                      params:(NSDictionary *)params                  httpMethod:(NSString *)httpMethod{    ASIFormDataRequest *request;    NSURL *url;    urlString = [kHttpBaseURLString stringByAppendingString:urlString];        if ([[httpMethod lowercaseString] isEqualToString:@"post"]) {        // post方式訪问接口        url = [NSURL URLWithString:urlString];        request = [ASIFormDataRequest requestWithURL:url];        [request setRequestMethod:@"POST"];                for (NSString *key in params) {            id value = [params objectForKey:key];            if (![value isKindOfClass:[NSData class]]) {                [request addPostValue:value forKey:key];            } else {                [request addData:value forKey:key];            }        }    } else {        // get方式訪问接口        urlString = [urlString stringByAppendingString:@"?format=json"];        for (NSString *key in params) {            urlString = [urlString stringByAppendingFormat:@"&%@=%@", key, [params objectForKey:key]];        }                NSLog(@"-----------url:%@-----------",urlString);                NSURL *url = [NSURL URLWithString:urlString];                request = [ASIFormDataRequest requestWithURL:url];        //设置缓存方式        //[request setSecondsToCache:60*60*24*30];        //[request setDownloadCache:[DFAppDelegate myCache]];        //设置缓存数据存储策略。这里採取的是假设无更新或无法联网就读取缓存数据        [request setCachePolicy:ASIAskServerIfModifiedCachePolicy|ASIFallbackToCacheIfLoadFailsCachePolicy];        [request setCacheStoragePolicy:ASICachePermanentlyCacheStoragePolicy];                [request setRequestMethod:@"GET"];    }        request.delegate = self;    request.timeOutSeconds = 60;    [request startAsynchronous];        self.httpReq = request;    self.urlString = urlString;}#pragma mark - ASIHTTPRequest delegate- (void)requestFinished:(ASIHTTPRequest *)request{    NSError *error = nil;    if (request.responseStatusCode == 500) {        // server状态500        error = [NSError errorWithDomain:@"server出错" code:-10000 userInfo:nil];    }    id result = [NSJSONSerialization JSONObjectWithData:request.responseData options:NSJSONReadingMutableContainers error:nil];    if ([result isKindOfClass:[NSDictionary class]]) {        NSString *status = [result objectForKey:@"status"];                if (![status isEqualToString:@"success"]) {            // 请求返回errorCode            error = [NSError errorWithDomain:[result objectForKey:@"info"] code:-9998 userInfo:nil];        }    } else {        error = [NSError errorWithDomain:@"server返回值出错" code:-9999 userInfo:nil];    }    if ([[HttpClient sharedClient] respondsToSelector:@selector(didFinishWithItem:error:)]) {        [[HttpClient sharedClient] performSelector:@selector(didFinishWithItem:error:) withObject:self withObject:error];    }}- (void)requestFailed:(ASIHTTPRequest *)request{    if ([[HttpClient sharedClient] respondsToSelector:@selector(didFinishWithItem:error:)]) {        [[HttpClient sharedClient] performSelector:@selector(didFinishWithItem:error:) withObject:self withObject:request.error];    }}@end

转载地址:http://pabxl.baihongyu.com/

你可能感兴趣的文章
Softmax函数
查看>>
hdu4462 Scaring the Birds
查看>>
设计中的道理_6
查看>>
MFC——AfxParseURL用法
查看>>
关于综合布线系统线缆挑选方法
查看>>
面向过程,面向对象,函数式对同一个问题的思考方式
查看>>
盘点:抵御网络攻击哪国强?世界20强国排名
查看>>
混合“白+黑”名单方法是如何帮助企业加强安全的?
查看>>
中国网速竟不到泰国一半、香港的1/4!名副其实"华囧"
查看>>
4G和5G不配物联网 不过死撑
查看>>
SAP宣布将投资22亿美元发展物联网业务
查看>>
他用10年前的攻击手法感染了17000多名开发者的电脑
查看>>
IBM秀出并行训练肌肉:256个GPU还能有95%的拓展效率,顺便刷新ImageNet-22K记录
查看>>
报告称云计算可能会阻碍IT支出
查看>>
《程序员度量:改善软件团队的分析学》一公平和一致性
查看>>
移动医疗行业6大值得关注的玩家解析
查看>>
Facebook 开源 FAISS;MIT 开发 SDV 系统,将合成数据用于机器学习等 | AI 开发者头条...
查看>>
联合光伏一季度太阳能发电站发电44.45万兆瓦时 同比增长67.8%
查看>>
如何建立一个正确的安全架构去做正确的防御?
查看>>
《程序员度量:改善软件团队的分析学》一可重复的成功
查看>>