IOS AFNetworking最新版本与NSFileManager自制缓存 - (pod ‘AFNetworking’)
说明 :
本次更新主要对AFNetworking进行二次封装并添加基于NSFileManager的详细缓存功能实现, 对应的GCD线程处理和数据缓存的失效时间等.
文章中尽量不使用或少使用封装, 目的是让大家清楚为了实现功能所需要的官方核心API是哪些(如果使用封装, 会在封装外面加以注释)
AFHTTPSessionManager的创建方法及相关知识点
核心API
class : AFHTTPSessionManager, AFHTTPResponseSerializer, AFNetworkReachability, GCD
delegate : 无
涉及的API : (API的官方详细注释(英文)详见本章结尾)
/** 1. 返回网络状态 */
- (void)setReachabilityStatusChangeBlock:(void (^)(AFNetworkReachabilityStatus status))block;
/** 2. POST */
- (NSURLSessionDataTask *)POST:(NSString *)URLString
parameters:(id)parameters
progress:(void (^)(NSProgress * _Nonnull))uploadProgress
success:(void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success
failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure;
/** 3. GET */
- (NSURLSessionDataTask *)GET:(NSString *)URLString
parameters:(id)parameters
progress:(void (^)(NSProgress * _Nonnull))downloadProgress
success:(void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success
failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure;
功能实现
思路
- 主要根据AFN给出的GET和POST请求进行封装, 返回直接可以使用的数据给程序员可以自己添加缓存时效.
2.缓存这里有参考EGO感觉简单明了, 对工程侵入比较小
- 利用代码来解析说明
(1). POST请求方法
/**
* POST
*
* @param param 入参
* @param urlStr 请求地址
* @param success 成功返回值
* @param fail 失败返回值
*/
- (void)httpManagerPostParameter:(NSDictionary *)param toHttpUrlStr:(NSString *)urlStr isCacheorNot:(BOOL)isCache targetViewController:(UIViewController *)viewController andUrlFunctionName:(NSString *)urlName success:(void(^)(id result))success orFail:(void(^)(NSError *error))fail {
switch (reachabilityStatus) {
case 0: {
if (![gs_CurrentFileManager objectForKey:gs_completeURL(gs_GetClass_Name(viewController), urlName)]) {
NSError *er = [[NSError alloc] initWithDomain:@"暂无缓存可用" code:10001 userInfo:nil];
fail(er);
return;
}
NSDictionary *jsonDic = [NSJSONSerialization JSONObjectWithData:(NSData *)[gs_CurrentFileManager objectForKey:gs_completeURL(gs_GetClass_Name(viewController), urlName)] options:NSJSONReadingMutableLeaves|NSJSONReadingMutableContainers error:nil];
success(jsonDic);
}
break;
default: {
[httpManager POST:urlStr parameters:param progress:^(NSProgress * _Nonnull uploadProgress) {
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
if (task.state == NSURLSessionTaskStateCompleted) {
NSDictionary *jsonDic = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableLeaves|NSJSONReadingMutableContainers error:nil];
if (isCache) {
[gs_CurrentFileManager setObject:responseObject forKey:gs_completeURL(gs_GetClass_Name(viewController), urlName) withTimeoutInterval:timeoutInterval];
}
success(jsonDic);
} else {
NSError *error = [[NSError alloc] initWithDomain:gs_Error_Network code:0 userInfo:nil];
fail(error);
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
fail(error);
}];
}
break;
}
}
(2). GET请求方法
- (void)httpManagerGetFromHttpUrlStr:(NSString *)urlStr withParameter:(NSDictionary *)param isCacheorNot:(BOOL)isCache targetViewController:(UIViewController *)viewController andUrlFunctionName:(NSString *)urlName success:(void(^)(id result))success orFail:(void(^)(NSError *error))fail {
switch (reachabilityStatus) {
case 0: {
if (![gs_CurrentFileManager objectForKey:gs_completeURL(gs_GetClass_Name(viewController), urlName)]) {
NSError *er = [[NSError alloc] initWithDomain:@"暂无缓存可用" code:10001 userInfo:nil];
fail(er);
return;
}
NSDictionary *jsonDic = [NSJSONSerialization JSONObjectWithData:(NSData *)[gs_sharedFileManager objectForKey:gs_completeURL(gs_GetClass_Name(viewController), urlName)] options:NSJSONReadingMutableLeaves|NSJSONReadingMutableContainers error:nil];
success(jsonDic);
}
break;
default: {
[httpManager GET:urlStr parameters:param progress:^(NSProgress * _Nonnull downloadProgress) {
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
if (task.state == NSURLSessionTaskStateCompleted) {
NSDictionary *jsonDic = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableLeaves|NSJSONReadingMutableContainers error:nil];
if (isCache) {
[gs_sharedFileManager setObject:responseObject forKey:gs_completeURL(gs_GetClass_Name(viewController), urlName) withTimeoutInterval:timeoutInterval];
}
success(jsonDic);
} else {
NSError *error = [[NSError alloc] initWithDomain:gs_Error_Network code:0 userInfo:nil];
fail(error);
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
fail(error);
}];
}
break;
}
}
(3). 网络状体判断
[gs_ReachabilityManager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
reachabilityStatus = status;
switch (status) {
case AFNetworkReachabilityStatusNotReachable: {
NSLog(@"无网络");
break;
}
case AFNetworkReachabilityStatusReachableViaWiFi:{
NSLog(@"WiFi网络");
break;
}
case AFNetworkReachabilityStatusReachableViaWWAN: {
NSLog(@"无线网络");
break;
}
default:
NSLog(@"不明网络");
break;
}
}];
(4). 封装类的单利创建以及GCD缓存线程创建
+ (instancetype)currentManager {
return [self sharedHttpManager];
}
+ (instancetype)sharedHttpManager {
static id instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[[self class] alloc] init];
});
return instance;
}
- (instancetype)init
{
httpManager = [AFHTTPSessionManager manager];
httpManager.responseSerializer = [AFHTTPResponseSerializer serializer];
[gs_ReachabilityManager startMonitoring];
timeoutInterval = 86400;/* 一天 */
return self;
}
(5). 使用到的工具宏成员变量以及头文件的引入
.h文件
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <AFNetworking.h>
#import "GSFileManager.h"
/**
* Reachability单利
*/
#define gs_ReachabilityManager [AFNetworkReachabilityManager sharedManager]
#define gs_HttpManager [GSHttpManager currentManager] /* 获取HttpManager单利 */
@interface GSHttpManager : NSObject
+ (instancetype)currentManager;
/**
* 判断网络
*/
- (void)httpManagerGSNetworkReachabilityManage;
/**
* POST
*/
- (void)httpManagerPostParameter:(NSDictionary *)param toHttpUrlStr:(NSString *)urlStr isCacheorNot:(BOOL)isCache targetViewController:(UIViewController *)viewController andUrlFunctionName:(NSString *)urlName success:(void(^)(id result))success orFail:(void(^)(NSError *error))fail;
/**
* GET
*/
- (void)httpManagerGetFromHttpUrlStr:(NSString *)urlStr withParameter:(NSDictionary *)param isCacheorNot:(BOOL)isCache targetViewController:(UIViewController *)viewController andUrlFunctionName:(NSString *)urlName success:(void(^)(id result))success orFail:(void(^)(NSError *error))fail;
@end
.m文件
#import "GSHttpManager.h"
#define gs_completeURL(base, component) [NSString stringWithFormat:@"%@%@",(base),(component)] /* 字符串拼接 */
/**
* 获取类的名字变作字符串
*/
#define gs_GetClass_Name(vc) [NSString stringWithUTF8String:object_getClassName(vc)] /* 获取类名 */
#define gs_Error_Network @"网络不给力"
@interface GSHttpManager () {
NSInteger reachabilityStatus;
AFHTTPSessionManager *httpManager;
NSTimeInterval timeoutInterval;
}
@end
@implementation GSHttpManager
@end
注意:因为方法中添加了对网络状态的判断, 当无网络时会读取本地的缓存, 所以需要在AppDelegate 先执行对网络状态的监测方法
[gs_ReachabilityManager startMonitoring];
[gs_HttpManager httpManagerGSNetworkReachabilityManage];