HIHTTPRequestManager.h
#import <Foundation/Foundation.h>
#ifndef hiDispatch_queue_async_safe
#define hiDispatch_queue_async_safe(queue, block)\
if (dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL) == dispatch_queue_get_label(queue)) {\
block();\
} else {\
dispatch_async(queue, block);\
}
#endif
#ifndef hiDispatch_main_async_safe
#define hiDispatch_main_async_safe(block) hiDispatch_queue_async_safe(dispatch_get_main_queue(), block)
#endif
NS_ASSUME_NONNULL_BEGIN
/// Ues this class to send the http request and manager the request task.
@interface HIHTTPRequestManager : NSObject
// Init
- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)manager;
// GET.
- (void)GETWithRequestTag:(NSInteger)requestTag
URLString:(NSString *)URLString
parameters:(nullable id)parameters
progress:(nullable void (^)(NSProgress *progress))progressCallback
success:(nullable void (^)(NSURLSessionDataTask * _Nullable task, id result))successCallback
failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failureCallback;
// POST.
- (void)POSTWithRequestTag:(NSInteger)requestTag
URLString:(NSString *)URLString
parameters:(nullable id)parameters
progress:(nullable void (^)(NSProgress *progress))progressCallback
success:(nullable void (^)(NSURLSessionDataTask * _Nullable task, id result))successCallback
failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failureCallback;
// Download
- (void)downloadTaskWithRequest:(NSURLRequest *)request
progress:(nullable void (^)(NSProgress *downloadProgress))progressCallback
destination:(nullable NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destinationCallback
completionHandler:(nullable void (^)(NSURLResponse *response, NSURL * _Nullable filePath, NSError * _Nullable error))completionCallback;
// the requesting task set.
@property (nonatomic, strong, readonly, nullable) NSHashTable *taskSet;
// cancel a request, cancel the request when dismiss before controller.
- (void)cancelTask:(NSInteger)requestTag;
@end
NS_ASSUME_NONNULL_END
HIHTTPRequestManager.m
#import "HIHTTPRequestManager.h"
#import "HIHTTPSessionManager.h"
@interface HIHTTPRequestManager ()
@property (nonatomic, strong, readwrite, nullable) NSHashTable *taskSet;
@property (nonatomic, strong) NSURLSessionDownloadTask *downloadTask;
@end
@implementation HIHTTPRequestManager
- (NSHashTable *)taskSet {
if (!_taskSet) {
_taskSet = [NSHashTable weakObjectsHashTable];
}
return _taskSet;
}
+ (instancetype)manager {
static HIHTTPRequestManager *_manager;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_manager = [[HIHTTPRequestManager alloc] init];
});
return _manager;
}
- (void)GETWithRequestTag:(NSInteger)requestTag
URLString:(NSString *)URLString
parameters:(nullable id)parameters
progress:(nullable void (^)(NSProgress *progress))progressCallback
success:(nullable void (^)(NSURLSessionDataTask * _Nullable task, id result))successCallback
failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failureCallback
{
__weak typeof(self)weakSelf = self;
NSURLSessionDataTask *task = [HIHTTPSessionManager GET:URLString parameters:parameters progress:progressCallback success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSString *jsonString = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSError *err;
id response = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&err];
if (err) {
response = jsonString;
}
hiDispatch_main_async_safe(^{
[weakSelf removeTask:task];
});
if (successCallback) {
successCallback(task,response);
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
hiDispatch_main_async_safe(^{
[weakSelf removeTask:task];
});
if (failureCallback) {
failureCallback(task,error);
}
}];
[task resume];
NSString *taskDescription = [self getTaskDescription:requestTag];
if (taskDescription) {
task.taskDescription = taskDescription;
[weakSelf.taskSet addObject:task];
}
}
- (void)POSTWithRequestTag:(NSInteger)requestTag
URLString:(NSString *)URLString
parameters:(nullable id)parameters
progress:(nullable void (^)(NSProgress *progress))progressCallback
success:(nullable void (^)(NSURLSessionDataTask * _Nullable task, id result))successCallback
failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failureCallback
{
__weak typeof(self)weakSelf = self;
NSURLSessionDataTask *task = [HIHTTPSessionManager POST:URLString parameters:parameters progress:progressCallback success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSString *jsonString = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSError *err;
id response = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&err];
if (err) {
response = jsonString;
}
hiDispatch_main_async_safe(^{
[weakSelf removeTask:task];
});
if (successCallback) {
successCallback(task,response);
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
hiDispatch_main_async_safe(^{
[weakSelf removeTask:task];
});
if (failureCallback) {
failureCallback(task,error);
}
}];
[task resume];
NSString *taskDescription = [self getTaskDescription:requestTag];
if (taskDescription) {
task.taskDescription = taskDescription;
[weakSelf.taskSet addObject:task];
}
}
- (void)downloadTaskWithRequest:(NSURLRequest *)request
progress:(nullable void (^)(NSProgress *downloadProgress))progressCallback
destination:(nullable NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destinationCallback
completionHandler:(nullable void (^)(NSURLResponse *response, NSURL * _Nullable filePath, NSError * _Nullable error))completionCallback
{
__weak typeof(self)weakSelf = self;
self.downloadTask = [HIHTTPSessionManager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) {
if (progressCallback) {
hiDispatch_main_async_safe(^{
progressCallback(downloadProgress);
});
}
} destination:destinationCallback completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
hiDispatch_main_async_safe(^{
[weakSelf removeTask:weakSelf.downloadTask];
});
if (completionCallback) {
completionCallback(response,filePath,error);
}
}];
[self.downloadTask resume];
NSString *taskDescription = request.URL.absoluteString;
if (taskDescription) {
self.downloadTask.taskDescription = taskDescription;
[self.taskSet addObject:self.downloadTask];
}
}
#pragma mark - task manager
- (void)cancelTask:(NSInteger)requestTag
{
NSString *taskDescription = [self getTaskDescription:requestTag];
for (NSURLSessionTask *task in self.taskSet) {
if ([task.taskDescription isEqualToString:taskDescription]) {
if (task.state < NSURLSessionTaskStateCanceling) {
[task cancel];
}
[self.taskSet removeObject:task];
}
}
}
- (void)removeTask:(NSURLSessionTask *)task
{
if ([self.taskSet containsObject:task]) {
[self.taskSet removeObject:task];
}
}
- (void)addTask:(NSURLSessionTask *)task
{
[self.taskSet addObject:task];
}
- (NSString *)getTaskDescription:(NSInteger)requestTag
{
return [NSString stringWithFormat:@"HIHTTPRequest: %ld",(long)requestTag];
}
@end
HIHTTPSessionManager.h
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/// This class is a manager of the HTTP request, there will use AFNetworking send a request in this class. Never add the App business code in this class.
@interface HIHTTPSessionManager : NSObject
+ (nullable NSURLSessionDataTask *)POST:(NSString *)URLString
parameters:(nullable id)parameters
progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgress
success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;
+ (nullable NSURLSessionDataTask *)GET:(NSString *)URLString
parameters:(nullable id)parameters
progress:(nullable void (^)(NSProgress *downloadProgress))downloadProgress
success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;
+ (nullable NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request
progress:(nullable void (^)(NSProgress *downloadProgress))downloadProgress
destination:(nullable NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination
completionHandler:(nullable void (^)(NSURLResponse *response, NSURL * _Nullable filePath, NSError * _Nullable error))completionHandler;
@end
NS_ASSUME_NONNULL_END
HIHTTPSessionManager.m
#import "HIHTTPSessionManager.h"
#import "AFHTTPSessionManager.h"
@implementation HIHTTPSessionManager
static AFHTTPSessionManager *_httpSessionManager = nil;
+ (AFHTTPSessionManager *)httpSessionManager {
if (_httpSessionManager == nil) {
// httpSessionManager
_httpSessionManager = [[AFHTTPSessionManager alloc] init];
// request out time set
_httpSessionManager.requestSerializer.timeoutInterval = 30.f;
// response serializer set
AFHTTPResponseSerializer *responseSerializer = [AFHTTPResponseSerializer serializer];
responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", @"text/html", @"text/xml", @"text/plain", nil];
_httpSessionManager.responseSerializer = responseSerializer;
// none securityPolicy
_httpSessionManager.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
// HTTP redirection
[_httpSessionManager setTaskWillPerformHTTPRedirectionBlock:^NSURLRequest * _Nonnull(NSURLSession * _Nonnull session, NSURLSessionTask * _Nonnull task, NSURLResponse * _Nonnull response, NSURLRequest * _Nonnull request) {
return request ? request : nil;
}];
}
return _httpSessionManager;
}
+ (nullable NSURLSessionDataTask *)POST:(NSString *)URLString
parameters:(nullable id)parameters
progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgress
success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure
{
return [[HIHTTPSessionManager httpSessionManager] POST:URLString parameters:parameters progress:uploadProgress success:success failure:failure];
}
+ (nullable NSURLSessionDataTask *)GET:(NSString *)URLString
parameters:(nullable id)parameters
progress:(nullable void (^)(NSProgress *downloadProgress))downloadProgress
success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure
{
return [[HIHTTPSessionManager httpSessionManager]GET:URLString parameters:parameters progress:downloadProgress success:success failure:failure];
}
+ (nullable NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request
progress:(nullable void (^)(NSProgress *downloadProgress))downloadProgress
destination:(nullable NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination
completionHandler:(nullable void (^)(NSURLResponse *response, NSURL * _Nullable filePath, NSError * _Nullable error))completionHandler
{
return [[HIHTTPSessionManager httpSessionManager] downloadTaskWithRequest:request progress:downloadProgress destination:destination completionHandler:completionHandler];
}
+ (void)cancelTask:(NSURLSessionTask *)task
{
[task cancel];
}
@end