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

- (void)requestWillBegin;
- (void)requestDidSucceedWithData:(id)data;
- (void)requestDidFailWithError:(NSError *)error; @end @interface RequestService : NSObject @property (nonatomic,assign)id<RequestServiceDelegate> 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 <NSObject>

- (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<HttpClientDelegate>)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<HttpClientDelegate>)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 <Foundation/Foundation.h>

@protocol HttpClientDelegate <NSObject>

- (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<HttpClientDelegate>)delegate; - (NSUInteger)requestWithUrl:(NSString *)urlString
params:(NSDictionary *)params
httpMethod:(NSString *)httpMethod
delegate:(id<HttpClientDelegate>)delegate
nTag:(NSInteger)nTag; - (NSUInteger)requestWithUrl:(NSString *)urlString
params:(NSDictionary *)params
httpMethod:(NSString *)httpMethod
delegate:(id<HttpClientDelegate>)delegate
sKey:(NSString *)sKey; - (NSUInteger)requestWithUrl:(NSString *)urlString
params:(NSDictionary *)params
httpMethod:(NSString *)httpMethod
delegate:(id<HttpClientDelegate>)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<HttpClientDelegate>)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<HttpClientDelegate>)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<HttpClientDelegate>)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<HttpClientDelegate>)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 <Foundation/Foundation.h>
#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<HttpClientDelegate> 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

ASIHttpRequest封装的更多相关文章

  1. 基于ASIHTTPRequest封装的HttpClient

    ASIHTTPRequest作为一个比较知名的http访问库本身功能比较强大,在项目开发过程中,如果每个请求,都要使用ASIHTTPRequest来写,有以下几个弊端: (1)繁琐,无封装性. (2) ...

  2. 用Block封装ASIHttpRequest

    用Block封装ASIHttpRequest 横方便的网络请求方法,不用每次都写代理方法.使代码先得很整齐,不会凌乱. 接口部分: // // LYHASIRequestBlock.h // ASIB ...

  3. 对ASIHTTPRequest的封装

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/quanqinayng/article/details/37659751 .h文件  // // Ht ...

  4. 强大的HTTP包装开源项目ASIHTTPRequest介绍

    ASIHTTPRequest 是一个直接在CFNetwork上做的开源项目,提供了一个比官方更方便更强大的HTTP网络传输的封装.它的特色功能如下: 1,下载的数据直接保存到内存或文件系统里 2,提供 ...

  5. ASIHTTPRequest详解 [经典]

    ASIHTTPRequest 对CFNetwork API进行了封装,并且使用起来非常简单,用Objective-C编写,可以很好的应用在Mac OS X系统和iOS平台的应用程序中.ASIHTTPR ...

  6. IOS学习笔记25—HTTP操作之ASIHTTPRequest

    IOS学习笔记25—HTTP操作之ASIHTTPRequest 分类: iOS2012-08-12 10:04 7734人阅读 评论(3) 收藏 举报 iosios5网络wrapper框架新浪微博 A ...

  7. ASIHTTPRequest类库简介和使用说明

    官方网站: http://allseeing-i.com/ASIHTTPRequest/ .可以从上面下载到最新源码,以及获取到相关的资料. 使用iOS SDK中的HTTP网络请求API,相当的复杂, ...

  8. iOS通过ASIHTTPRequest提交JSON数据

    先验知识——什么是ASIHTTPRequest? 使用iOS SDK中的HTTP网络请求API,相当的复杂,调用很繁琐,ASIHTTPRequest就是一个对CFNetwork API进行了封装,并且 ...

  9. iOS - ASIHTTPRequest 网络请求

    前言 使用 iOS SDK 中的 HTTP 网络请求 API,相当的复杂,调用很繁琐,ASIHTTPRequest 就是一个对 CFNetwork API 进行了封装,并且使用起来非常简单的一套 AP ...

随机推荐

  1. 利用Python imaplib和email模块 读取邮件文本内容及附件内容

    python使用imap接收邮件的过程探索 https://www.cnblogs.com/yhlx/archive/2013/03/22/2975817.html #! encoding:utf8 ...

  2. div设置contentEditable="true"作为文本编辑器,定位光标解决办法

    function set_focus(el) {    el = el[0]; // jquery 对象转dom对象    el.focus();    if ($.browser.msie) {   ...

  3. js怎么让时间函数的秒数在页面上显示是变化的

    <input type="text" id="showtime" value="" /><script type=&quo ...

  4. PLSQL Developer新手使用教程(图文教程)

    PLSQL Developer是Oracle数据库开发工具,很牛也很好用,PLSQL Developer功能很强大,可以做为集成调试器,有SQL窗口,命令窗口,对象浏览器和性能优化等功能,下面简单的介 ...

  5. Linux 下 ps 命令

    简述 Linux中的ps命令是Process Status的缩写.ps命令用来列出系统中当前运行的那些进程.ps命令列出的是当前那些进程的快照,就是执行ps命令的那个时刻的那些进程,动态的显示进程信息 ...

  6. 【C#/WPF】保存BitmapImage数据到文件中

    参考: http://stackoverflow.com/questions/35804375/how-do-i-save-a-bitmapimage-from-memory-into-a-file- ...

  7. linux后台运行jar程序

    Linux 运行jar包命令如下: 方式一:java -jar XXX.jar特点:当前ssh窗口被锁定,可按CTRL + C打断程序运行,或直接关闭窗口,程序退出那如何让窗口不锁定? 方式二java ...

  8. CentOs6.5 安装rabbitmq(转)

    // 安装预环境 yum install gcc gcc-c++ yum install zlib zlin-devel ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 / ...

  9. CentOS ext4 磁盘分区 格式化 挂载

    [root@appserver ~]# df -h /*查看现有分区情况*/文件系统 容量 已用 可用 已用%% 挂载点/dev/vda1 9.9G 8.2G 1.2G 88% /tmpfs 3.9G ...

  10. Zend Studio 配置

    2.更改Zend字体 依次进入Window——Preferences——General——Appearance——Colors and Fonts——Basic——Text Font进行修改,偶还是喜 ...