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": " ...
随机推荐
- nginx和tomcat的优化
测试脚本(服务器414报错)#!/bin/bashurl=http://192.168.4.5/for i in {1..5000}do url=${url}v$i=idoneecho $url #a ...
- Oracle 实例名/服务名 请问SID和Service_Name有什么区别啊?
可以简单的这样理解:一个公司比喻成一台服务器,数据库是这个公司中的一个部门. 1.SID:一个数据库可以有多个实例(如RAC),SID是用来标识这个数据库内部每个实例的名字, 就好像一个部门里,每个人 ...
- Learning-Python【10】:函数初识
一.什么是函数 函数就是代码的一种组织形式,是指将一组语句的集合通过一个名字(函数名)封装起来,要想指向这个函数,只需要调用其函数名即可 函数分为两大类:内置函数 和 自定义函数 二.为何要用函数 减 ...
- Signal in unit is connected to following multiple drivers VHDL
参考链接 https://blog.csdn.net/jbb0523/article/details/6946899 出错原因 两个Process都对LDS_temp进行了赋值,万一在某个时刻,在两个 ...
- Spring-AOP环绕监听出错
Exception in thread "main" org.springframework.aop.AopInvocationException: Null return val ...
- 剑指offer 05:用两个栈实现队列
题目描述 用两个栈来实现一个队列,完成队列的Push和Pop操作. 队列中的元素为int类型. 解题代码 import java.util.Stack; public class Solution{ ...
- python使用os.listdir和os.walk获得文件的路径
python使用os.listdir和os.walk获得文件的路径 目录 情况1:在一个目录下面只有文件,没有文件夹,这个时候可以使用os.listdir 情况2:递归的情况,一个目录下面既有目录 ...
- 【Core】.NET Core 部署在Linux
安装.NET Core SDK 在CentOS上 1.右键打开命令行: 2.为了安装.NET,需要注册微软签名密钥和添加微软相关的支持.这个操作每台机器只能做一次. Add the dotnet p ...
- Verification of Model Transformations A Survey of the State-of-the-Art 模型转换的验证 对现状的调查
模型驱动工程范式认为软件开发生命周期由工件(需求规范.分析和设计文档.测试套件.源代码)支持,这些工件是表示要构建的系统不同视图的模型.存在一个由模型转换驱动的(半)自动构造过程,从系统的抽象模型开始 ...
- linux grep find查找文件夹、代码中的某行/字符串
本文转载于:https://blog.csdn.net/Mr_Cat123/article/details/80541658 在Linux中,由于文件很多,代码很长,可能我们只知道其中的一两个字符串, ...