AFN 二次封装
#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 二次封装的更多相关文章
- iOS项目相关@AFN&SDWeb的二次封装
一,AFNetworking跟SDWebImge是功能强大且常用的第三方,然而在实际应用中需要封装用来复用今天就跟大家分享一下AFN&SDWeb的二次封装 1. HttpClient.h及.m ...
- iOS菜鸟之AFN的二次封装
我用一个单例类将一些常用的网络请求进行了二次封装,主要包括post请求 get请求 图片文件上传下载 视频的断点续传等功能. 首先大家先去github上下载AFN,将文件夹内的AFNetworki ...
- Swift -- 对AFN框架的封装
Swift -- 对AFN框架的封装 一.封装AFN的目的 简单的说: 解耦 日常工作中,我们一般都不会去直接使用AFNetWorking来直接发送网络请求,因为耦合性太强,假设有多个控制器都使用AF ...
- 对百度WebUploader开源上传控件的二次封装,精简前端代码(两句代码搞定上传)
前言 首先声明一下,我这个是对WebUploader开源上传控件的二次封装,底层还是WebUploader实现的,只是为了更简洁的使用他而已. 下面先介绍一下WebUploader 简介: WebUp ...
- Quick Cocos (2.2.5plus)CoinFlip解析(MenuScene display AdBar二次封装)
转载自:http://cn.cocos2d-x.org/tutorial/show?id=1621 从Samples中找到CoinFlip文件夹,复制其中的 res 和 script 文件夹覆盖新建工 ...
- 对jquery的ajax进行二次封装以及ajax缓存代理组件:AjaxCache
虽然jquery的较新的api已经很好用了, 但是在实际工作还是有做二次封装的必要,好处有:1,二次封装后的API更加简洁,更符合个人的使用习惯:2,可以对ajax操作做一些统一处理,比如追加随机数或 ...
- Android 应用程序集成Google 登录及二次封装
谷歌登录API: https://developers.google.com/identity/sign-in/android/ 1.注册并且登录google网站 https://accounts. ...
- Android 应用程序集成FaceBook 登录及二次封装
1.首先在Facebook 开发者平台注册一个账号 https://developers.facebook.com/ 开发者后台 https://developers.facebook.com/ap ...
- 对jquery的ajax进行二次封装
第一种方法: $(function(){ /** * ajax封装 * url 发送请求的地址 * data 发送到服务器的数据,数组存储,如:{"username": " ...
随机推荐
- 2018-2019-1 20189206 《Linux内核原理与分析》第八周作业
#linux内核分析学习笔记 --第七章 可执行程序工作原理 学习目标:了解一个可执行程序是如何作为一个进程工作的. ELF文件 目标文件:是指由汇编产生的(*.o)文件和可执行文件. 即 可执行或可 ...
- ArchLinux 无密码Samba 配置
安装上迅雷后就必须把硬盘挂上去开个Samba,然后边下电影边看,这就是一个Nas了. 开搞! pacman -S samba 安装samba,然后进入/etc/samba/目录 vim smb.con ...
- Spring NoSuchBeanDefinitionException六大原因总结
1. Overview In this article, we are discussing the Springorg.springframework.beans.factory.NoSuchBea ...
- P1908 逆序对
传送门 这题似乎不应该出现在这里.. 日常做法(归并): #include<iostream> #include<cstdio> #include<algorithm&g ...
- python 获取文件目录位置
test.py import os print('***获取当前目录***') print(os.getcwd()) print(os.path.abspath(os.path.dirname(__f ...
- grade配置添加java库导致报 java.lang.RuntimeException: java.lang.RuntimeException: com.android.builder.dexing.DexArchiveMerger
原因是导入的第三方库中也引入了项目中存在的相同名称的库,导致产生冲突
- js时间戳转化成日期格式
function timestampToTime(timestamp) { var date = new Date(timestamp * 1000);//时间戳为10位需*1000,时间戳为13位的 ...
- SpringMVC使用Swagger
Swagger 是一个规范和完整的框架,用于生成.描述.调用和可视化 RESTful 风格的 Web 服务.总体目标是使客户端和文件系统作为服务器以同样的速度来更新.文件的方法,参数和模型紧密集成到服 ...
- codeforces 343d
题意:一棵树结构上有水,往一个节点加水,那么所有的子节点都会有水,或者排干一个节点的水,那么它的上面的节点都会没水. 用dfs序,数组记录区间内全部有水为1,区间内有没水的点就为0. 倒水:区间更新, ...
- noip模拟ernd
[题目背景]解决了第一题之后,你打开了第二题.这是一道关于树的题目,你很快想出了一个复杂度和树的直径有关的算法,可以通过所有的数据.不过,你的做法常数似乎有点大.为了更好地卡常,你决定构造一些数据来检 ...