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": " ...
随机推荐
- win10虚拟桌面使用方法-提高工作效率
任务栏右键 => 显示任务视图按钮 然后坐下角出现的任务视图按钮可以添加虚拟桌面 快捷键: win + ctrl + 左/右 切换桌面 win + tab 打开任务视图 win + ctrl + ...
- 关于 使用python向qq好友发送消息(对爬虫的作用----当程序执行完毕或者报错无限给自己qq发送消息,直到关闭)
以前看到网上一些小程序,在处理完事物后会自动发送qq消息,但是一直搞不懂是说明原理.也在网上找过一些python登陆qq发送消息的文字,但是都太复杂了.今天偶然看到一篇文章,是用python调用win ...
- 获取Tomcat更详细的日志
前言 有时候tomcat报错未详细,未能定位到原因. 解决方法: 获取更详细的日志,以便调试. 详细步骤: 获取详细的日志,方法如下: 在WEB-INF/classes目录下logging.pro ...
- ShareSVN授权的代码示例
var targetUrl = "your svn url path"; var path = "Temp"; System.Collections.Objec ...
- loj#3 -Copycat
原题链接:https://loj.ac/problem/3 题目描述: --- Copycat 内存限制:256 MiB 时间限制:1000 ms 输入文件: copycat.in 输出文件: cop ...
- JS中for in 与 for of
// 数组var A=[4,6,74,67]; for in:拿到的是数组下标 for (let i in A){ console.log(i); } //0,1,2,3 for of:拿到的是数组元 ...
- 温顾知新系列-JAVA网络编程系统(1)- 流
一.字节流 1. 输出流 Java的基本输出流类是java.io.OutputStream; public abstract calss OutputStream 此类常用的写入数据的基本方法如下: ...
- Go语言学习之10 Web开发与Mysql数据库
本节主要内容: 1. http编程2. mysql使用 1. http编程 (1)http编程分析 Go原生支持http,import(“net/http”) Go的http服务性能和nginx比较接 ...
- jTimer
很多时候我们需要按时间间隔执行一个任务,当满足一定条件时停止执行.此插件旨在解决这一经常遇到的问题. jTimer: (function ($) { $.extend({ timer: funct ...
- 机器学习 之KNN近邻法
目录 1.KNN近邻法 1.KNN近邻法 KNN模型由三个基本要素决定: 距离度量:其中欧式距离一般误差最小,\(x_{i} 和 x_{j}\)为两个样本点:\[L_{2}(x_{i}, x_{j}) ...