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