原理:先给NSURLSession地Configuration设置一个内存和本地代理,原来的网络请求结束后会查找缓存的代理字典,并执行代理对象对应的操作方法,需要做的就是拦截错误的方法,返回缓存的数据

AFURLSessionManager.m

- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration {
self = [super init];
if (!self) {
return nil;
} if (!configuration) {
configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
} self.sessionConfiguration = configuration; #pragma mark 在这里给网络加上一个缓存
[self addURLCacheForRequestSession:configuration]; self.operationQueue = [[NSOperationQueue alloc] init];
self.operationQueue.maxConcurrentOperationCount = ; self.session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.operationQueue]; self.responseSerializer = [AFJSONResponseSerializer serializer]; self.securityPolicy = [AFSecurityPolicy defaultPolicy]; #if !TARGET_OS_WATCH
self.reachabilityManager = [AFNetworkReachabilityManager sharedManager];
#endif self.mutableTaskDelegatesKeyedByTaskIdentifier = [[NSMutableDictionary alloc] init]; self.lock = [[NSLock alloc] init];
self.lock.name = AFURLSessionManagerLockName; [self.session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {
for (NSURLSessionDataTask *task in dataTasks) {
[self addDelegateForDataTask:task uploadProgress:nil downloadProgress:nil completionHandler:nil];
} for (NSURLSessionUploadTask *uploadTask in uploadTasks) {
[self addDelegateForUploadTask:uploadTask progress:nil completionHandler:nil];
} for (NSURLSessionDownloadTask *downloadTask in downloadTasks) {
[self addDelegateForDownloadTask:downloadTask progress:nil destination:nil completionHandler:nil];
}
}]; return self;
} #pragma mark 添加缓存
-(void)addURLCacheForRequestSession:(NSURLSessionConfiguration*)configuration
{
if ([[[UIDevice currentDevice] systemVersion] compare:@"8.2" options:NSNumericSearch] == NSOrderedAscending) {
configuration.URLCache = [NSURLCache sharedURLCache];
}
else {
configuration.URLCache = [[NSURLCache alloc] initWithMemoryCapacity: * *
diskCapacity: * *
diskPath:@"customer_request_cache"];
}
}

AFURLSessionManagerTaskDelegate  实现方法添加部分代码

#pragma mark - NSURLSessionTaskDelegate

- (void)URLSession:(__unused NSURLSession *)session
task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error
{
__strong AFURLSessionManager *manager = self.manager; __block id responseObject = nil; __block NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
userInfo[AFNetworkingTaskDidCompleteResponseSerializerKey] = manager.responseSerializer; //Performance Improvement from #2672
NSData *data = nil;
if (self.mutableData) {
data = [self.mutableData copy];
//We no longer need the reference, so nil it out to gain back some memory.
self.mutableData = nil;
} if (self.downloadFileURL) {
userInfo[AFNetworkingTaskDidCompleteAssetPathKey] = self.downloadFileURL;
} else if (data) {
userInfo[AFNetworkingTaskDidCompleteResponseDataKey] = data;
} if (error) {
#pragma mark 网络错误时读取网络缓存数据
if (error.code == -) {
NSURLCache *cache = self.manager.session.configuration.URLCache;
if (cache) {
NSCachedURLResponse *response = [cache cachedResponseForRequest:task.currentRequest];
dispatch_async(url_session_manager_processing_queue(), ^{
NSError *serializationError = nil;
responseObject = [manager.responseSerializer responseObjectForResponse:response.response data:response.data error:&serializationError]; if (self.downloadFileURL) {
responseObject = self.downloadFileURL;
} if (responseObject) {
userInfo[AFNetworkingTaskDidCompleteSerializedResponseKey] = responseObject;
} if (serializationError) {
userInfo[AFNetworkingTaskDidCompleteErrorKey] = serializationError;
} dispatch_group_async(manager.completionGroup ?: url_session_manager_completion_group(), manager.completionQueue ?: dispatch_get_main_queue(), ^{
if (self.completionHandler) {
self.completionHandler(response.response, responseObject, serializationError);
}
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidCompleteNotification object:task userInfo:userInfo];
});
});
});
}
}
else {
userInfo[AFNetworkingTaskDidCompleteErrorKey] = error; dispatch_group_async(manager.completionGroup ?: url_session_manager_completion_group(), manager.completionQueue ?: dispatch_get_main_queue(), ^{
if (self.completionHandler) {
self.completionHandler(task.response, responseObject, error);
} dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidCompleteNotification object:task userInfo:userInfo];
});
});
} } else {
dispatch_async(url_session_manager_processing_queue(), ^{
NSError *serializationError = nil;
responseObject = [manager.responseSerializer responseObjectForResponse:task.response data:data error:&serializationError]; if (self.downloadFileURL) {
responseObject = self.downloadFileURL;
} if (responseObject) {
userInfo[AFNetworkingTaskDidCompleteSerializedResponseKey] = responseObject;
} if (serializationError) {
userInfo[AFNetworkingTaskDidCompleteErrorKey] = serializationError;
} dispatch_group_async(manager.completionGroup ?: url_session_manager_completion_group(), manager.completionQueue ?: dispatch_get_main_queue(), ^{
if (self.completionHandler) {
self.completionHandler(task.response, responseObject, serializationError);
} dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidCompleteNotification object:task userInfo:userInfo];
});
});
});
}
}
//网络请求错误代码
enum {
NSURLErrorUnknown = -,
NSURLErrorCancelled = -,
NSURLErrorBadURL = -,
NSURLErrorTimedOut = -,
NSURLErrorUnsupportedURL = -,
NSURLErrorCannotFindHost = -,
NSURLErrorCannotConnectToHost = -,
NSURLErrorDataLengthExceedsMaximum = -,
NSURLErrorNetworkConnectionLost = -,
NSURLErrorDNSLookupFailed = -,
NSURLErrorHTTPTooManyRedirects = -,
NSURLErrorResourceUnavailable = -,
NSURLErrorNotConnectedToInternet = -,
NSURLErrorRedirectToNonExistentLocation = -,
NSURLErrorBadServerResponse = -,
NSURLErrorUserCancelledAuthentication = -,
NSURLErrorUserAuthenticationRequired = -,
NSURLErrorZeroByteResource = -,
NSURLErrorCannotDecodeRawData = -,
NSURLErrorCannotDecodeContentData = -,
NSURLErrorCannotParseResponse = -,
NSURLErrorInternationalRoamingOff = -,
NSURLErrorCallIsActive = -,
NSURLErrorDataNotAllowed = -,
NSURLErrorRequestBodyStreamExhausted = -,
NSURLErrorFileDoesNotExist = -,
NSURLErrorFileIsDirectory = -,
NSURLErrorNoPermissionsToReadFile = -,
NSURLErrorSecureConnectionFailed = -,
NSURLErrorServerCertificateHasBadDate = -,
NSURLErrorServerCertificateUntrusted = -,
NSURLErrorServerCertificateHasUnknownRoot = -,
NSURLErrorServerCertificateNotYetValid = -,
NSURLErrorClientCertificateRejected = -,
NSURLErrorClientCertificateRequired = -,
NSURLErrorCannotLoadFromNetwork = -,
NSURLErrorCannotCreateFile = -,
NSURLErrorCannotOpenFile = -,
NSURLErrorCannotCloseFile = -,
NSURLErrorCannotWriteToFile = -,
NSURLErrorCannotRemoveFile = -,
NSURLErrorCannotMoveFile = -,
NSURLErrorDownloadDecodingFailedMidStream = -,
NSURLErrorDownloadDecodingFailedToComplete = -
}

给AFNetworking添加请求缓存功能实现在没有网络的情况下返回缓存数据的更多相关文章

  1. 微信小程序POST请求参数传递不到后台, 前台获取不到后端返回的数据, 以及 post 请求返回 404 但后台能收到数据

    1 微信小程序POST请求参数传递不到后台 需要在微信请求 wx.request 改变默认 header 配置为如下 wx.request({ url: 'test.php', //仅为示例,并非真实 ...

  2. Okhttp设置http缓存,在没有网络的情况下加载http缓存里面的内容

    HTTP_CACHE_FILENAME为缓存地址根路径: private final String HTTP_CACHE_FILENAME = "HttpCache"; priva ...

  3. localstorage实现带过期时间的缓存功能

    前言 一般可以使用cookie,localstorage,sessionStorage来实现浏览器端的数据缓存,减少对服务器的请求. 1.cookie数据存放在本地硬盘中,只要在过期时间之前,都是有效 ...

  4. (转)全面认识一下.NET 4的缓存功能

    很多关于.NET 4.0新特性的介绍,缓存功能的增强肯定是不会被忽略的一个重要亮点.在很多文档中都会介绍到在.NET 4.0中,缓存功能的增强主要是在扩展性方面做了改进,改变了原来只能利用内存进行缓存 ...

  5. iOS UIWebview添加请求头的两种方式

    1.在UIWebviewDelegate的方法中拦截request,设置request的请求头,废话不多说看代码: - (BOOL)webView:(UIWebView *)webView shoul ...

  6. 【Java/Android性能优5】 Android ImageCache图片缓存,使用简单,支持预取,支持多种缓存算法,支持不同网络类型,扩展性强

    本文转自:http://www.trinea.cn/android/android-imagecache/ 主要介绍一个支持图片自动预取.支持多种缓存算法.支持二级缓存.支持数据保存和恢复的图片缓存的 ...

  7. 【高并发】高并发环境下构建缓存服务需要注意哪些问题?我和阿里P9聊了很久!

    写在前面 周末,跟阿里的一个朋友(去年晋升为P9了)聊了很久,聊的内容几乎全是技术,当然了,两个技术男聊得最多的话题当然就是技术了.从基础到架构,从算法到AI,无所不谈.中间又穿插着不少天马行空的想象 ...

  8. Volley网络框架完全解析(缓存篇)

    在上一篇中讲完了Volley框架怎么使用,那么这篇就来讲讲Volley框架的缓存机制 我们看Volley内部源码发现: Volley框架内部自己处理了DiskBasedCache硬盘缓存,但是没有处理 ...

  9. 防抖与节流 & 若每个请求必须发送,如何平滑地获取最后一个接口返回的数据

    博客地址:https://ainyi.com/79 日常浏览网页中,在进行窗口的 resize.scroll 或者重复点击某按钮发送请求,此时事件处理函数或者接口调用的频率若无限制,则会加重浏览器的负 ...

随机推荐

  1. [转载]js正则表达式/replace替换变量方法

    原文地址:http://www.blogjava.net/pingpang/archive/2012/08/12/385342.html JavaScript正则实战(会根据最近写的不断更新) 1.j ...

  2. Java定时任务示例

    package com.my.timer; import java.util.Date; import java.util.TimerTask; public class myTask extends ...

  3. 转: 如何使用jstack分析线程状态

    这个讲的好系列:  如何使用jstack分析线程状态 转:http://www.jianshu.com/p/6690f7e92f27 背景 记得前段时间,同事说他们测试环境的服务器cpu使用率一直处于 ...

  4. 我要搬家到csdn,大家到那里来看我吧,平台更大,看到的人更多!

    ruby代码 #encoding: utf-8 require 'net/http' require 'open-uri' require 'nokogiri' # 用于解析html的模块 # sud ...

  5. 浏览器对HTML5特性检測工具Modernizr

    近期在做公司移动端运营的项目,需求中多处地方都会涉及动画. 相信非常多前端开发都会有这样的感触,对CSS3中的动画属性非常熟悉,可是因为对动画运动过程的理解不深入,经常仅仅能望而止步.CSS3中动画这 ...

  6. MYSQL 线程池

    https://www.jianshu.com/p/88e606eca2a5 https://www.percona.com/doc/percona-server/LATEST/performance ...

  7. idea 导入 android项目

    1. 2. 主要是勾选上面选项. next next 导入即可

  8. 腾讯云快速完成python3.6开发环境搭建与django应用部署

    [本文出自天外归云的博客园] 部署python3.6.5 腾讯云服务器安装python3竟然要3个多小时!而且一度速度为0…… 于是网查据说是腾讯云服务器连python官网缓慢导致的,所以想找个国内的 ...

  9. Android——RecycleView

    RecycleView设置点击事件 http://blog.csdn.net/guxiao1201/article/details/40423361

  10. Spring Security 认证流程

    请求之间共享SecurityContext原因: