#import "YQDataManager.h"
#import <YYModel/YYModel.h>
#pragma mark - 数据model基类
@implementation YQListBaseModel
+ (NSDictionary *)modelCustomPropertyMapper
{
return @{};
}
@end
@implementation YQDataBaseModel
+ (NSDictionary *)modelCustomPropertyMapper
{
return @{};
}
@end
@implementation YQBaseModel
+ (NSDictionary *)modelCustomPropertyMapper
{
return @{};
}
@end
#pragma mark - 网络请求基类
///请求类型类型
typedef NS_ENUM(NSUInteger, YQNetWorkType) {
YQNetWorkTypeGet,//get请求
YQNetWorkTypeHttpPost,//入参Http格式Post请求
YQNetWorkTypeJsonPost,//入参json格式Post请求
};
/**
* 请求重试计数器
*/
@interface RetryCounter : NSObject
//重试次数,默认30次
@property (nonatomic, assign) NSInteger retryCount;
//已重试的次数
@property (nonatomic, assign) NSInteger retryTime;
//重试时间间隔,默认100毫秒
@property (nonatomic, assign) NSTimeInterval retryInterval;
//计算器id
@property (nonatomic, assign) NSInteger counterId;
- (instancetype)initWithHash:(NSUInteger)hash;
- (BOOL)canRetry;
@end
@implementation RetryCounter
- (instancetype)initWithHash:(NSUInteger)hash
{
self = [super init];
//set default value
self.retryCount = 1;
self.retryInterval = 0.1;
self.counterId = hash;
return self;
}
/**
* 是否可以重试,如果是,则返回true,并且重试次数自增1.
*
* @return 是否可以重试
*/
- (BOOL)canRetry {
BOOL result = (_retryTime < _retryCount);
if (result) {
_retryTime++;
}
return result;
}
@end
@interface YQDataManager ()
@property (nonnull, nonatomic, strong) NSMutableArray *retryCounterList;
@end
@implementation YQDataManager
/**
* 创建单例
*
* @return return value description
*/
+ (YQDataManager *)manager {
static YQDataManager *sharedManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
configuration.timeoutIntervalForRequest = 8.0;
configuration.timeoutIntervalForResource = 8.0;
/* 创建网络请求对象 */
sharedManager = [[YQDataManager alloc] initWithBaseURL:[NSURL URLWithString:BaseUrl] sessionConfiguration:configuration];
/* 设置请求和接收的数据编码格式 */
sharedManager.responseSerializer = [AFJSONResponseSerializer serializer]; // 设置接收数据为 JSON 数据
sharedManager.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
sharedManager.securityPolicy.allowInvalidCertificates = YES;
// 修改 解析数据格式 能够接受的内容类型 - 官方推荐的做法,民间做法:直接修改 AFN 的源代码
sharedManager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json",@"text/json",@"text/javascript", @"text/html",nil];
sharedManager.retryCounterList = [NSMutableArray array];
});
return sharedManager;
}
#pragma mark - helper
- (RetryCounter*)retryCounterForHash:(NSUInteger)hash
{
RetryCounter *target = nil;
for (RetryCounter *counter in _retryCounterList) {
if (counter.counterId == hash) {
target = counter;
break;
}
}
return target;
}
- (RetryCounter*)insertCounterWithHash:(NSUInteger)hash
{
RetryCounter *counter = [[RetryCounter alloc] initWithHash:hash];
[[YQDataManager manager].retryCounterList addObject:counter];
return counter;
}
- (void)removeCounterForHash:(NSUInteger)hash
{
RetryCounter *counter = [self retryCounterForHash:hash];
if (counter != nil) {
[_retryCounterList removeObject:counter];
}
}
#pragma mark - http process
/**
* 重试的方法
*/
+ (void)networkMananger:(YQDataManager *)manager
method:(YQNetWorkType)httpMethod
retryWithUrl:(NSString*)url
params:(NSDictionary*)param
success:(void(^)(id responseData))successBlock
failure:(void(^)(NSError *error))failureBlock {
RetryCounter *currentCounter = [[YQDataManager manager] retryCounterForHash:param.hash];
if (currentCounter == nil) {
//add to retry counter list
currentCounter = [[YQDataManager manager] insertCounterWithHash:param.hash];
}
BOOL retryFlag = [currentCounter canRetry];
//wait for 10ms
NSDate *endDate = [NSDate dateWithTimeIntervalSinceNow:currentCounter.retryInterval];
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:endDate];
if (httpMethod == YQNetWorkTypeGet) {
[manager GET:url parameters:param progress:nil success:^(NSURLSessionDataTask *task, id responseData) {
successBlock(responseData);
//remove counter
[[YQDataManager manager] removeCounterForHash:param.hash];
} failure:^(NSURLSessionDataTask *task, NSError *error) {
if (retryFlag) {
//retry
[YQDataManager networkMananger:manager method:httpMethod retryWithUrl:url params:param success:successBlock failure:failureBlock];
} else {
failureBlock(error);
//remove counter
[[YQDataManager manager] removeCounterForHash:param.hash];
}
}];
}else if (httpMethod == YQNetWorkTypeJsonPost){
manager.requestSerializer = [AFJSONRequestSerializer serializer]; // 设置请求数据为 JSON 数据
[manager POST:url parameters:param progress:nil success:^(NSURLSessionDataTask *task, id responseData) {
successBlock(responseData);
//remove counter
[[YQDataManager manager] removeCounterForHash:param.hash];
} failure:^(NSURLSessionDataTask *task, NSError *error) {
if (retryFlag) {
//retry
[YQDataManager networkMananger:manager method:httpMethod retryWithUrl:url params:param success:successBlock failure:failureBlock];
} else {
failureBlock(error);
//remove counter
[[YQDataManager manager] removeCounterForHash:param.hash];
}
}];
}else{
manager.requestSerializer = [AFHTTPRequestSerializer serializer];
[manager POST:url parameters:param progress:nil success:^(NSURLSessionDataTask *task, id responseData) {
successBlock(responseData);
//remove counter
[[YQDataManager manager] removeCounterForHash:param.hash];
} failure:^(NSURLSessionDataTask *task, NSError *error) {
if (retryFlag) {
//retry
[YQDataManager networkMananger:manager method:httpMethod retryWithUrl:url params:param success:successBlock failure:failureBlock];
} else {
failureBlock(error);
//remove counter
[[YQDataManager manager] removeCounterForHash:param.hash];
}
}];
}
}
/**
* 网络请求的底层方法
*/
+ (void)networkProcessWithUrl:(NSString *)url
params:(NSDictionary *)aParams
method:(YQNetWorkType )httpMethod
modelClass:(Class)modelClass
responseBlock:(YQNetworkResult)respBlock
{
YQDataManager *manager = [YQDataManager manager];
NSString *fullPath = [NSString stringWithFormat:@"%@%@",manager.baseURL,url];
if (aParams) {
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:aParams options:0 error:&error];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSLog(@"url : %@, param ==== %@", fullPath, jsonString);
}else{
NSLog(@"url : %@, param ==== %@", fullPath, aParams);
}
if (httpMethod == YQNetWorkTypeGet) {
if ([UserManager isLogin]) {
UserInfo *info= [UserManager getUserObject];
NSDictionary *headerFieldValueDictionary = @{@"token":info.token, @"usercode":info.userCode};
if (headerFieldValueDictionary != nil) {
for (NSString *httpHeaderField in headerFieldValueDictionary.allKeys) {
NSString *value = headerFieldValueDictionary[httpHeaderField];
[manager.requestSerializer setValue:value forHTTPHeaderField:httpHeaderField];
}
}
}
[manager GET:fullPath parameters:aParams progress:nil success:^(NSURLSessionDataTask *task, id responseData) {
[YQDataManager successProcessWithModelClass:modelClass result:responseData block:respBlock];
} failure:^(NSURLSessionDataTask *task, NSError *error) {
[YQDataManager networkMananger:manager method:httpMethod retryWithUrl:url params:aParams success:^(id respData) {
[YQDataManager successProcessWithModelClass:modelClass result:respData block:respBlock];
} failure:^(NSError *error) {
[YQDataManager failureProcess:error block:respBlock];
}];
}];
} else if (httpMethod == YQNetWorkTypeJsonPost) {
if ([UserManager isLogin]) {
UserInfo *info= [UserManager getUserObject];
NSDictionary *headerFieldValueDictionary = @{@"token":info.token, @"userMobile":info.userMobile};
if (headerFieldValueDictionary != nil) {
for (NSString *httpHeaderField in headerFieldValueDictionary.allKeys) {
NSString *value = headerFieldValueDictionary[httpHeaderField];
[manager.requestSerializer setValue:value forHTTPHeaderField:httpHeaderField];
}
}
}
manager.requestSerializer = [AFJSONRequestSerializer serializer]; // 设置请求数据为 JSON 数据
[manager POST:fullPath parameters:aParams progress:nil success:^(NSURLSessionDataTask *task, id responseData) {
[YQDataManager successProcessWithModelClass:modelClass result:responseData block:respBlock];
} failure:^(NSURLSessionDataTask *task, NSError *error) {
[YQDataManager networkMananger:manager method:httpMethod retryWithUrl:url params:aParams success:^(id respData) {
[YQDataManager successProcessWithModelClass:modelClass result:respData block:respBlock];
} failure:^(NSError *error) {
[YQDataManager failureProcess:error block:respBlock];
}];
}];
}else{
manager.requestSerializer = [AFHTTPRequestSerializer serializer];
[manager POST:fullPath parameters:aParams progress:nil success:^(NSURLSessionDataTask *task, id responseData) {
[YQDataManager successProcessWithModelClass:modelClass result:responseData block:respBlock];
} failure:^(NSURLSessionDataTask *task, NSError *error) {
[YQDataManager networkMananger:manager method:httpMethod retryWithUrl:url params:aParams success:^(id respData) {
[YQDataManager successProcessWithModelClass:modelClass result:respData block:respBlock];
} failure:^(NSError *error) {
[YQDataManager failureProcess:error block:respBlock];
}];
}];
}
}
/**
* 接口请求成功返回
*/
+ (void)successProcessWithModelClass:(Class)modelClass
result:(id)responseData
block:(YQNetworkResult)block
{
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:responseData options:NSJSONWritingPrettyPrinted error:nil];
NSString *jsonStr = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSLog(@"====%@",jsonStr);
if (!block) {
return;
}
//model
if (modelClass == nil) {
if (block) {
block(YES, nil, responseData);
}
} else {
YQBaseModel *item = [YQBaseModel yy_modelWithJSON:responseData];
if ([item.status isEqualToString:@"SUCCESS"]) {//返回成功状态
if ([item.data isKindOfClass:[NSDictionary class]]) {
id model = [modelClass yy_modelWithJSON:item.data];
if (block) {
block(YES, item, model);
}
}else{
if (item.data) {
NSDictionary *josnDic = @{@"data":item.data };
id model = [modelClass yy_modelWithJSON:josnDic];
if (block) {
block(YES, item, model);
}
}else{
if (block) {
block(YES, item, nil);
}
}
}
}else{//返回失败状态
if (block) {
NSError *error = [YQDataManager errorWithDescription:item.message cede:item.code];
block(NO, item, error);
}
}
}
}
/**
* 接口请求失败无返回
*/
+ (void)failureProcess:(NSError *)error block:(YQNetworkResult)block
{
NSLog(@"error: %@,userInfo = %@",error, [error userInfo]);
if (block) {
block(NO, nil, error);
}
}
/**
* get方式请求调用方法
*/
+ (void)getDataWithUrl:(NSString *)url
Params:(NSDictionary *)params
modelClass:(Class)modelClass
responseBlock:(YQNetworkResult)respBlock
{
[YQDataManager networkProcessWithUrl:url params:params method:YQNetWorkTypeGet modelClass:modelClass responseBlock:respBlock];
}
/**
* post 请求调用方式 入参Json请求数据
*/
+ (void)postDataJsonRequestWithUrl:(NSString *)url
Params:(NSDictionary *)params
modelClass:(Class)modelClass
responseBlock:(YQNetworkResult)respBlock
{
[YQDataManager networkProcessWithUrl:url params:params method:YQNetWorkTypeJsonPost modelClass:modelClass responseBlock:respBlock];
}
/**
* post 请求调用方法 入参Http请求数据
*/
+ (void)postDataHttpRequestWithUrl:(NSString *)url
Params:(NSDictionary *)params
modelClass:(Class)modelClass
responseBlock:(YQNetworkResult)respBlock
{
[YQDataManager networkProcessWithUrl:url params:params method:YQNetWorkTypeHttpPost modelClass:modelClass responseBlock:respBlock];
}
#pragma mark - Utils
/**
* 请求成功返回失败状态时创建错误返回
*/
+ (NSError*)errorWithDescription:(NSString *)errorMsg cede:(NSInteger)code
{
NSString *msg = errorMsg;
if (msg == nil) {
msg = @"未知错误";
code = 22222;
}
NSDictionary *userInfo = @{NSLocalizedDescriptionKey: msg};
NSError *error = [NSError errorWithDomain:@"dongze" code:code userInfo:userInfo];
return error;
}
@end