//
// ASIHTTPRequest+Request.h
// CloudShopping
//
// Created by sixiaobo on 14-7-9.
// Copyright (c) 2014年 com.Uni2uni. All rights reserved.
//
#import "ASIFormDataRequest.h"
#import "ASIDownloadCache.h"
// downloadData是返回的数据,如果出错,会把错误放到error中,否则error为nil,可通过error参数
// 判断是否出错
typedef void(^HYBResultBlock)(NSData *downloadData, NSError *error);
//
// HYBRequestType枚举用于指定请求类型
typedef NS_ENUM(NSUInteger, HYBRequestType) {
kTypePost = 1 << 1, // POST请求
kTypeGet = 1 << 2 // GET请求
};
@interface HYBHttpRequest : ASIFormDataRequest
// 请求回调block,成功或者失败都会回调此block,通过error参数判断是否成功
@property (nonatomic, copy) HYBResultBlock resultBlock;
@property (nonatomic, strong) NSMutableData *downloadData; // 下载完成后的数据
@property (nonatomic, assign) HYBRequestType requestType;
// 异步请求方式
/*!
* @brief 默认使用POST请求方式
* @param path 网络请求前缀参数
* @param params 使用字典存储,会在内部拼接到请求网址中
* @param completion 完成时的回调block
* @return 返回HYBHttpRequest对象
*/
- (id)initWithPath:(NSString *)path
params:(NSDictionary *)params
completion:(HYBResultBlock)completion;
- (id)initWithPath:(NSString *)path
params:(NSDictionary *)params
completion:(HYBResultBlock)completion
isCache:(BOOL)isCache // 是否缓存,POST请求默认是NO
isRefresh:(BOOL)isRefresh; // 是否刷新缓存
- (id)initWithPath:(NSString *)path
params:(NSDictionary *)params
requestType:(HYBRequestType)requestType
completion:(HYBResultBlock)completion;
- (id)initWithPath:(NSString *)path
params:(NSDictionary *)params
requestType:(HYBRequestType)requestType
completion:(HYBResultBlock)completion
isCache:(BOOL)isCache // 是否缓存,POST请求默认是NO;
isRefresh:(BOOL)isRefresh; // 是否刷新缓存
- (id)initWithPath:(NSString *)path
requestType:(HYBRequestType)requestType
completion:(HYBResultBlock)completion;
- (id)initWithPath:(NSString *)path
requestType:(HYBRequestType)requestType
completion:(HYBResultBlock)completion
isCache:(BOOL)isCache // 是否缓存,POST请求默认是NO;
isRefresh:(BOOL)isRefresh; // 是否刷新缓存
// 必须是POST请求,请求参数要转换成JSON格式数据
- (id)initWithPath:(NSString *)path
postBody:(NSMutableData *)postBodyJSONData
completion:(HYBResultBlock)completion;
// 必须是POST请求,请求参数要转换成JSON格式数据
- (id)initWithPath:(NSString *)path
postBody:(NSMutableData *)postBodyJSONData
completion:(HYBResultBlock)completion
isCache:(BOOL)isCache // 是否缓存,POST请求默认是NO;
isRefresh:(BOOL)isRefresh; // 是否刷新缓存
// 取消请求
- (void)cancelRequest;
@end
//
// ASIHTTPRequest+Request.m
// CloudShopping
//
// Created by sixiaobo on 14-7-9.
// Copyright (c) 2014年 com.Uni2uni. All rights reserved.
//
#import "HYBHTTPRequest.h"
#import "ASIFormDataRequest.h"
#import "NSString+Common.h"
#import "HYBHttpRequestManager.h"
#import "NSString+Encrypt.h"
#import "NSFileManager+File.h"
@interface HYBHttpRequest ()
@property (nonatomic, assign) BOOL isCache;
@property (nonatomic, assign) BOOL isRefresh;
@property (nonatomic, copy) NSString *fileName;
@end
@implementation HYBHttpRequest
- (id)initWithPath:(NSString *)path
params:(NSDictionary *)params
requestType:(HYBRequestType)requestType
completion:(HYBResultBlock)completion {
return [self initWithPath:path
params:params
requestType:requestType
completion:completion
isCache:requestType == kTypeGet
isRefresh:NO];
}
- (id)initWithPath:(NSString *)path
params:(NSDictionary *)params
completion:(HYBResultBlock)completion
isCache:(BOOL)isCache // 是否缓存,POST请求默认是NO
isRefresh:(BOOL)isRefresh { // 是否刷新缓存
return [self initWithPath:path
params:params
requestType:kTypePost
completion:completion
isCache:isCache
isRefresh:isRefresh];
}
- (id)initWithPath:(NSString *)path
params:(NSDictionary *)params
requestType:(HYBRequestType)requestType
completion:(HYBResultBlock)completion
isCache:(BOOL)isCache
isRefresh:(BOOL)isRefresh {
if (self = [super initWithURL:[NSURL URLWithString:path]]) {
self.isCache = isCache;
self.delegate = self;
self.resultBlock = [completion copy];
self.downloadData = [[NSMutableData alloc] init];
self.requestType = requestType;
self.fileName = path;
self.isRefresh = isRefresh;
if (self.requestType == kTypeGet) {
[self setRequestMethod:@"GET"];
// 设置永久存储在本地
} else if (self.requestType == kTypePost) {
[self setRequestMethod:@"POST"];
[self addRequestHeader:@"Content-Type" value:@"application/json"];
if (params) {
self.fileName = [NSString stringWithFormat:@"%@?", self.fileName];
for (NSString *key in params.allKeys) {
[self addPostValue:[params objectForKey:key] forKey:key];
self.fileName = [NSString stringWithFormat:@"%@%@=%@",
self.fileName, key, [params objectForKey:key]];
}
}
}
// 如果是缓存
// 且不刷新缓存
if (self.isRefresh == NO && self.isCache && [[NSFileManager defaultManager] isFileExists:[self cachePath]]) {
if (![[NSFileManager defaultManager] isFile:[self cachePath] timeout:12 * 60 * 60]) {
NSData *data = [[NSData alloc] initWithContentsOfFile:[self cachePath]];
self.downloadData = [data mutableCopy];
if (data.length != 0) {
self.resultBlock(data, nil);
return self;
}
}
}
[[HYBHttpRequestManager sharedRequestManager] addRequest:self
withKey:self.fileName.md5];
[self startAsynchronous];
}
return self;
}
- (id)initWithPath:(NSString *)path params:(NSDictionary *)params completion:(HYBResultBlock)completion {
return [self initWithPath:path params:params requestType:kTypePost completion:completion];
}
- (id)initWithPath:(NSString *)path
completion:(HYBResultBlock)completion {
return [self initWithPath:path params:nil completion:completion];
}
- (id)initWithPath:(NSString *)path
requestType:(HYBRequestType)requestType
completion:(HYBResultBlock)completion {
return [self initWithPath:path
params:nil
requestType:requestType
completion:completion
isCache:requestType == kTypeGet
isRefresh:NO];
}
- (id)initWithPath:(NSString *)path
requestType:(HYBRequestType)requestType
completion:(HYBResultBlock)completion
isCache:(BOOL)isCache // 是否缓存,POST请求默认是NO;
isRefresh:(BOOL)isRefresh { // 是否刷新缓存
return [self initWithPath:path
params:nil
requestType:requestType
completion:completion
isCache:isCache
isRefresh:isRefresh];
}
// 必须是POST请求,请求参数要转换成JSON格式数据
- (id)initWithPath:(NSString *)path
postBody:(NSMutableData *)postBodyJSONData
completion:(HYBResultBlock)completion {
return [self initWithPath:path
postBody:postBodyJSONData
completion:completion
isCache:NO
isRefresh:YES];
}
- (id)initWithPath:(NSString *)path
postBody:(NSMutableData *)postBodyJSONData
completion:(HYBResultBlock)completion
isCache:(BOOL)isCache // 是否缓存,POST请求默认是NO;
isRefresh:(BOOL)isRefresh { // 是否刷新缓存
if (self = [super initWithURL:[NSURL URLWithString:path]]) {
self.delegate = self;
self.resultBlock = [completion copy];
self.downloadData = [[NSMutableData alloc] init];
self.requestType = kTypePost;
self.isCache = isCache;
self.isRefresh = isRefresh;
self.fileName = path;
if (postBodyJSONData.length != 0) {
NSString *str = [[NSString alloc] initWithData:postBodyJSONData
encoding:NSUTF8StringEncoding];
self.fileName = [NSString stringWithFormat:@"%@%@", self.fileName, str];
}
if (self.requestType == kTypePost) {
[self setRequestMethod:@"POST"];
[self addRequestHeader:@"Content-Type" value:@"application/json"];
[self addRequestHeader:@"Accept" value:@"application/json"];
[self setPostBody:postBodyJSONData];
}
// 如果是缓存
// 且不刷新缓存
if (self.isRefresh == NO && self.isCache && [[NSFileManager defaultManager] isFileExists:[self cachePath]]) {
if (![[NSFileManager defaultManager] isFile:[self cachePath] timeout:12 * 60 * 60]) {
NSData *data = [[NSData alloc] initWithContentsOfFile:[self cachePath]];
self.downloadData = [data mutableCopy];
if (data.length != 0) {
self.resultBlock(data, nil);
return self;
}
}
}
[[HYBHttpRequestManager sharedRequestManager] addRequest:self
withKey:self.fileName.md5];
[self startAsynchronous];
}
return self;
}
- (void)cancelRequest {
[self clearDelegatesAndCancel];
return;
}
#pragma mark - ASIHttpRequestDelegate
- (void)request:(ASIHTTPRequest *)request didReceiveResponseHeaders:(NSDictionary *)responseHeaders {
[self.downloadData setLength:0];
return;
}
- (void)requestFinished:(ASIHTTPRequest *)request {
[[HYBHttpRequestManager sharedRequestManager] removeRequestWithKey:self.fileName.md5];
if (self.resultBlock) {
[self.downloadData writeToFile:[self cachePath] atomically:YES];
self.resultBlock(self.downloadData, nil);
}
return;
}
- (void)requestFailed:(ASIHTTPRequest *)request {
[[HYBHttpRequestManager sharedRequestManager] removeRequestWithKey:self.fileName.md5];
if (self.resultBlock) {
[self clearDelegatesAndCancel];
self.resultBlock(self.downloadData, self.error);
}
return;
}
- (void)request:(ASIHTTPRequest *)request didReceiveData:(NSData *)data {
[self.downloadData appendData:data];
return;
}
#pragma mark - 获取缓存路径
- (NSString *)cachePath {
return [NSString stringWithFormat:@"%@/%@", [NSString cachePath], self.fileName.md5];
}
@end
//
// HYBHttpRequestManager.h
// CloudShopping
//
// Created by sixiaobo on 14-7-9.
// Copyright (c) 2014年 com.Uni2uni. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "ASIHTTPRequest.h"
#import "ASIDownloadCache.h"
/*!
* @brief 管理ASIHttpRequest对象的生命周期
* @author huangyibiao
*/
@interface HYBHttpRequestManager : NSObject
@property (nonatomic, strong) ASIDownloadCache *downloadCache;
+ (HYBHttpRequestManager *)sharedRequestManager;
/*!
* @brief 添加ASIHttpRequest对象,用过管理其生命周期
* @param request 需要交由HYBHttpRequestManager来管理的请求对象
* @param urlStringKey 使用绝对网址作为key
*/
- (void)addRequest:(id)request withKey:(NSString *)urlStringKey;
/*!
* @brief 根据指定的key清除请求对象的代理、取消请求并移除掉HYBHttpReuest对象
* @param urlStringKey 绝对网址
*/
- (void)removeRequestWithKey:(NSString *)urlStringKey;
/*!
* @brief 这里需要慎重,一旦调用,就会把所有的请求对象都移除掉
*/
- (void)removeAllRequest;
/*!
* @brief 取消所有请求,并且移除
*/
- (void)cancelAllRequestAndRemove;
@end
//
// HYBHttpRequestManager.m
// CloudShopping
//
// Created by sixiaobo on 14-7-9.
// Copyright (c) 2014年 com.Uni2uni. All rights reserved.
//
#import "HYBHttpRequestManager.h"
#import "HYBHTTPRequest.h"
@interface HYBHttpRequestManager ()
@property (nonatomic, strong) NSMutableDictionary *requestDict;
@end
@implementation HYBHttpRequestManager
+ (HYBHttpRequestManager *)sharedRequestManager {
static HYBHttpRequestManager *sharedManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (!sharedManager) {
sharedManager = [[[self class] alloc] init];
}
});
return sharedManager;
}
- (id)init {
if (self = [super init]) {
self.requestDict = [[NSMutableDictionary alloc] init];
}
return self;
}
- (void)addRequest:(id)request withKey:(NSString *)urlStringKey {
NSString *error = [NSString stringWithFormat:@"error in %s, key is nil", __FUNCTION__];
NSAssert(urlStringKey != nil, error);
[self.requestDict setObject:request forKey:urlStringKey];
return;
}
- (void)removeRequestWithKey:(NSString *)urlStringKey {
NSString *error = [NSString stringWithFormat:@"error in %s, key is nil", __FUNCTION__];
NSAssert(urlStringKey != nil, error);
id request = [self.requestDict objectForKey:urlStringKey];
if ([request isKindOfClass:[ASIHTTPRequest class]]) {
[request clearDelegatesAndCancel];
} else {
NSURLConnection *connection = (NSURLConnection *)request;
[connection cancel];
}
[self.requestDict removeObjectForKey:urlStringKey];
return;
}
- (void)removeAllRequest {
[self.requestDict removeAllObjects];
return;
}
- (void)cancelAllRequestAndRemove {
for (ASIHTTPRequest *request in self.requestDict.allValues) {
[request clearDelegatesAndCancel];
}
[self.requestDict removeAllObjects];
return;
}
@end