#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

AFN 二次封装的更多相关文章

  1. iOS项目相关@AFN&SDWeb的二次封装

    一,AFNetworking跟SDWebImge是功能强大且常用的第三方,然而在实际应用中需要封装用来复用今天就跟大家分享一下AFN&SDWeb的二次封装 1. HttpClient.h及.m ...

  2. iOS菜鸟之AFN的二次封装

    我用一个单例类将一些常用的网络请求进行了二次封装,主要包括post请求 get请求  图片文件上传下载  视频的断点续传等功能. 首先大家先去github上下载AFN,将文件夹内的AFNetworki ...

  3. Swift -- 对AFN框架的封装

    Swift -- 对AFN框架的封装 一.封装AFN的目的 简单的说: 解耦 日常工作中,我们一般都不会去直接使用AFNetWorking来直接发送网络请求,因为耦合性太强,假设有多个控制器都使用AF ...

  4. 对百度WebUploader开源上传控件的二次封装,精简前端代码(两句代码搞定上传)

    前言 首先声明一下,我这个是对WebUploader开源上传控件的二次封装,底层还是WebUploader实现的,只是为了更简洁的使用他而已. 下面先介绍一下WebUploader 简介: WebUp ...

  5. Quick Cocos (2.2.5plus)CoinFlip解析(MenuScene display AdBar二次封装)

    转载自:http://cn.cocos2d-x.org/tutorial/show?id=1621 从Samples中找到CoinFlip文件夹,复制其中的 res 和 script 文件夹覆盖新建工 ...

  6. 对jquery的ajax进行二次封装以及ajax缓存代理组件:AjaxCache

    虽然jquery的较新的api已经很好用了, 但是在实际工作还是有做二次封装的必要,好处有:1,二次封装后的API更加简洁,更符合个人的使用习惯:2,可以对ajax操作做一些统一处理,比如追加随机数或 ...

  7. Android 应用程序集成Google 登录及二次封装

    谷歌登录API:  https://developers.google.com/identity/sign-in/android/ 1.注册并且登录google网站 https://accounts. ...

  8. Android 应用程序集成FaceBook 登录及二次封装

    1.首先在Facebook 开发者平台注册一个账号 https://developers.facebook.com/ 开发者后台  https://developers.facebook.com/ap ...

  9. 对jquery的ajax进行二次封装

    第一种方法: $(function(){ /** * ajax封装 * url 发送请求的地址 * data 发送到服务器的数据,数组存储,如:{"username": " ...

随机推荐

  1. Java IO流及应用(一)

    IO流 IO流概述及FileWriter类的使用 FileReader类使用 缓冲流介绍和使用 IO流相关案例 NO.one IO流概述及FileWriter类使用 1.1 IO流概述及分类 IO流用 ...

  2. Mac OS X 清除DNS缓存

    参考: Flushing your DNS cache in Mac OS X and Linux Mac OS X 清除DNS缓存 根据Mac OS X操作系统的版本选择以下命令: Mac OS X ...

  3. Windows下命令行怎样登录MySQL

    直接cmd回车然后 “ mysql -u root -p  ”  登录时出现错误,原来是权限不够 打开cmd时需要以管理员的身份打开 然后继续使用 “ mysql -u root -p ” 还是不行, ...

  4. HDU 2612 (2次BFS,有点小细节)

    Problem Description Pass a year learning in Hangzhou, yifenfei arrival hometown Ningbo at finally. L ...

  5. caffe-windows画loss与accuracy曲线

    参考博客: http://blog.csdn.net/sunshine_in_moon/article/details/53541573 进入tools/extra/文件夹中,修改plot_train ...

  6. 如何使用 Deepfakes 换脸

    如何使用 Deepfakes 换脸 1. 获取deepfakes工具包 git clone https://github.com/deepfakes/faceswap.git 2. 补齐依赖包: pi ...

  7. 一个时代的终结:为什么是时候放弃ITOM四大巨头了?这对IT领导者来说意味着什么?

    ​​关注嘉为科技,获取运维新知 2018年7月,Broadcom宣布了收购CA Technologies的计划,收购额近190亿美元.虽然分析师对于芯片制造商收购企业级软件公司这件事是否值得还在进行激 ...

  8. HTTP协议(二)之确保web安全的HTTPS

    一.概述 https并非是应用层的一种新协议.只是HTTP通信接口部分用SSL和TLS协议替代. 通常,HTTP直接和TCP通信.当使用SSL时,则演变成先和SSL通信,再由SSL和TCP通信了. 简 ...

  9. 7.1 通用的职责分配软件原则 GRASP原则一: 创建者 Creator

    1.GRASP原则一: 创建者 Creator  Who should be responsible for creating a new instance of some class 由谁来负责创 ...

  10. Configure the Stanford segmenter for NLTK

    >>> from nltk.tokenize.stanford_segmenter import StanfordSegmenter >>> segmenter = ...