网络请求封装

简介:
//
//  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


目录
相关文章
|
1天前
|
存储 算法 JavaScript
< 今日小技巧:Axios封装,接口请求增加防抖功能 >
今天这篇文章,主要是讲述对axios封装的请求,由于部分请求可能存在延时的情况。使得接口可能存在会被持续点击(即:接口未响应的时间内,被持续请求),导致重复请求的问题,容易降低前后端服务的性能!故提出给axios封装的配置里面,新增一个防抖函数,用来限制全局请求的防抖。
< 今日小技巧:Axios封装,接口请求增加防抖功能 >
|
1月前
|
前端开发
AJAX发送请求方法封装和请求函数底层刨析以及axios二次封装
AJAX发送请求方法封装和请求函数底层刨析以及axios二次封装
|
2月前
|
API
uniApp封装请求
uniApp封装请求
14 0
|
8月前
|
存储 小程序 前端开发
小程序封装网络请求和拦截器
在开发小程序时,实际上我们通常需要封装网络请求和拦截器,以实现统一处理状态码和存储用户登录信息等功能。这样可以提高开发效率,减少代码重复,同时也可以提高代码的可维护性和可读性。
147 0
|
10月前
|
Java
网络请求工具类WebServiceUtils
网络请求工具类WebServiceUtils
|
11月前
请求方法封装
请求方法封装
|
11月前
uiapp请求方法封装
uiapp请求方法封装
|
11月前
|
前端开发
封装ajax请求接口
封装ajax请求接口
85 0
|
12月前
|
消息中间件 JavaScript 小程序
OkHttp完美封装,一行搞完外部请求
OkHttp完美封装,一行搞完外部请求