详细解析几个和网络请求有关的类(十六) —— NSURLCach
版本记录
版本号 | 时间 |
---|---|
V1.0 | 2018.03.15 |
前言
我们做APP发起网络请求,一般都是使用框架,这些框架的底层也都是苹果的API,接下来几篇就一起来看一下和网络有关的几个类。感兴趣的可以看上面几篇文章。
1. 详细解析几个和网络请求有关的类 (一) —— NSURLSession
2. 详细解析几个和网络请求有关的类(二) —— NSURLRequest和NSMutableURLRequest
3. 详细解析几个和网络请求有关的类(三) —— NSURLConnection
4. 详细解析几个和网络请求有关的类(四) —— NSURLSession和NSURLConnection的区别
5. 详细解析几个和网络请求有关的类(五) —— 关于NSURL加载系统(一)
6. 详细解析几个和网络请求有关的类(六) —— 使用NSURLSession(二)
7. 详细解析几个和网络请求有关的类(七) —— URL数据的编码和解码(三)
8. 详细解析几个和网络请求有关的类(八) —— 处理重定向和其他请求更改(四)
9. 详细解析几个和网络请求有关的类(九) —— 身份验证挑战和TLS链验证(五)
10. 详细解析几个和网络请求有关的类(十) —— 理解获取缓存(六)
11. 详细解析几个和网络请求有关的类(十一) —— Cookies和自定义协议(七)
12. 详细解析几个和网络请求有关的类(十二) —— URL Session的生命周期(八)
13. 详细解析几个和网络请求有关的类(十三) —— NSURLResponse(一)
14. 详细解析几个和网络请求有关的类(十四) —— NSHTTPCookie(一)
15. 详细解析几个和网络请求有关的类(十五) —— NSHTTPCookieStorage(一)
回顾
上一篇讲述关于NSHTTPCookieStorage
,下面这篇我们就主要看一下NSURLCache
。
基本信息
下面我们就看一下该类的基本信息。
将URL请求映射到缓存的响应对象的对象。
1. Overview
NSURLCache
类通过将NSURLRequest
对象映射到NSCachedURLResponse
对象来实现缓存对URL加载请求的响应。 它提供了复合内存和磁盘缓存,并允许您操纵内存和磁盘部分的大小。 您还可以控制缓存数据持久存储的路径。
注意:在iOS中,当系统磁盘空间不足时,磁盘缓存可能被清空,但只有当您的应用程序未运行时。
2. Thread Safety - 线程安全
在iOS 8和更高版本以及MacOS 10.10和更高版本中,NSURLCache
是线程安全的。
尽管NSURLCache实例方法可以安全地从多个执行上下文中同时调用,但请注意,当尝试读取或写入同一请求的响应时,像cachedResponseForRequest:和storeCachedResponse:forRequest:这样的方法具有不可避免的竞争情况。
NSURLCache
的子类必须以这种线程安全的方式实现重写的方法。
Topics
1. Getting and setting shared cache - 获取和设置共享cache
-
sharedURLCache
- 返回共享的
NSURLCache
实例对象。
- 返回共享的
2. Creating a new cache object - 创建新的缓存对象
-
- initWithMemoryCapacity:diskCapacity:diskPath:
- 根据指定的值实例化NSURLCache对象。
3. Getting and storing cached objects - 获取和存储缓存对象
-
- cachedResponseForRequest:
- 为指定的URL请求返回缓存中的缓存URL响应。
-
- storeCachedResponse:forRequest:
- 存储指定请求的缓存URL响应。
- - getCachedResponseForDataTask:completionHandler:
- - storeCachedResponse:forDataTask:
4. Removing cached objects - 移动缓存对象
-
- removeCachedResponseForRequest:
- 移动指定URL请求的URL响应缓存对象。
- - removeCachedResponseForDataTask:
- - removeCachedResponsesSinceDate:
-
- removeAllCachedResponses
- 清除接收者的缓存,删除所有存储的缓存的URL响应。
5. Getting and setting on-disk cache properties - 获取和设置磁盘缓存属性
-
currentDiskUsage
- 接收者在磁盘缓存的当前大小(以字节为单位)
-
diskCapacity
- 接收者的磁盘缓存容量(以字节为单位)。
6. Getting and setting in-memory cache properties - 获取和设置内存缓存属性
-
currentMemoryUsage
- 接收方内存中缓存的当前大小(以字节为单位)。
-
memoryCapacity
- 接收方内存中缓存的容量(以字节为单位)。
API
1. NSURLCache本类
下面我们就看一下API相关文档。
@class NSURLRequest;
@class NSURLCacheInternal;
@interface NSURLCache : NSObject
{
@private
NSURLCacheInternal *_internal;
}
/*!
@property sharedURLCache
@abstract Returns the shared NSURLCache instance or
sets the NSURLCache instance shared by all clients of
the current process. This will be the new object returned when
calls to the <tt>sharedURLCache</tt> method are made.
@discussion Unless set explicitly through a call to
<tt>+setSharedURLCache:</tt>, this method returns an NSURLCache
instance created with the following default values:
<ul>
<li>Memory capacity: 4 megabytes (4 * 1024 * 1024 bytes)
<li>Disk capacity: 20 megabytes (20 * 1024 * 1024 bytes)
<li>Disk path: <nobr>(user home directory)/Library/Caches/(application bundle id)</nobr>
</ul>
<p>Users who do not have special caching requirements or
constraints should find the default shared cache instance
acceptable. If this default shared cache instance is not
acceptable, <tt>+setSharedURLCache:</tt> can be called to set a
different NSURLCache instance to be returned from this method.
Callers should take care to ensure that the setter is called
at a time when no other caller has a reference to the previously-set
shared URL cache. This is to prevent storing cache data from
becoming unexpectedly unretrievable.
@result the shared NSURLCache instance.
*/
// @abstract 返回共享NSURLCache实例或设置当前进程的所有客户端共享的NSURLCache实例。
// 这个是调用方法sharedURLCache返回的新的实例。
// @discussion 除非明确的调用+setSharedURLCache:,这个方法返回一个NSURLCache由下面默认值创建的实例对象。
// Memory capacity: 4 megabytes (4 * 1024 * 1024 bytes)
// Disk capacity: 20 megabytes (20 * 1024 * 1024 bytes)
// Disk路径(user home directory)/Library/Caches/(application bundle id)
// 没有特殊缓存需求或限制的用户应该找到默认的共享缓存实例。
// 如果此默认共享缓存实例不可接受,则可以调用+ setSharedURLCache来设置从此
// 方法返回的另一个NSURLCache实例。 调用者应该注意确保在其他调用者没有参考先前设置的共享URL缓存的时候调用setter。
// 这是为了防止存储缓存数据意外无法恢复。
@property (class, strong) NSURLCache *sharedURLCache;
/*!
@method initWithMemoryCapacity:diskCapacity:diskPath:
@abstract Initializes an NSURLCache with the given capacity and
path.
@discussion The returned NSURLCache is backed by disk, so
developers can be more liberal with space when choosing the
capacity for this kind of cache. A disk cache measured in the tens
of megabytes should be acceptable in most cases.
@param memoryCapacity the capacity, measured in bytes, for the cache in memory.
@param diskCapacity the capacity, measured in bytes, for the cache on disk.
@param path the path on disk where the cache data is stored.
@result an initialized NSURLCache, with the given capacity, backed
by disk.
*/
// 根据指定的存储量和路径实例化对象。返回的NSURLCache由磁盘支持,
// 因此在为这种缓存选择容量时,开发人员可以更加自由地使用空间。
// 在大多数情况下,以几十兆字节度量的磁盘缓存应该是可以接受的。
- (instancetype)initWithMemoryCapacity:(NSUInteger)memoryCapacity diskCapacity:(NSUInteger)diskCapacity diskPath:(nullable NSString *)path;
/*!
@method cachedResponseForRequest:
@abstract Returns the NSCachedURLResponse stored in the cache with
the given request.
@discussion The method returns nil if there is no
NSCachedURLResponse stored using the given request.
@param request the NSURLRequest to use as a key for the lookup.
@result The NSCachedURLResponse stored in the cache with the given
request, or nil if there is no NSCachedURLResponse stored with the
given request.
*/
// 返回的是缓存中存储的给定请求的NSCachedURLResponse对象,
// 如果不存在这样的对象,那么就返回nil。
- (nullable NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request;
/*!
@method storeCachedResponse:forRequest:
@abstract Stores the given NSCachedURLResponse in the cache using
the given request.
@param cachedResponse The cached response to store.
@param request the NSURLRequest to use as a key for the storage.
*/
// 在缓存中存储给定请求的NSCachedURLResponse对象
- (void)storeCachedResponse:(NSCachedURLResponse *)cachedResponse forRequest:(NSURLRequest *)request;
/*!
@method removeCachedResponseForRequest:
@abstract Removes the NSCachedURLResponse from the cache that is
stored using the given request.
@discussion No action is taken if there is no NSCachedURLResponse
stored with the given request.
@param request the NSURLRequest to use as a key for the lookup.
*/
// 移除使用给定请求存储的NSCachedURLResponse对象
- (void)removeCachedResponseForRequest:(NSURLRequest *)request;
/*!
@method removeAllCachedResponses
@abstract Clears the given cache, removing all NSCachedURLResponse
objects that it stores.
*/
// 清楚给定的缓存,移除所有存储的NSCachedURLResponse对象。
- (void)removeAllCachedResponses;
/*!
@method removeCachedResponsesSince:
@abstract Clears the given cache of any cached responses since the provided date.
*/
// 移除指定日期到现在的缓存数据
- (void)removeCachedResponsesSinceDate:(NSDate *)date API_AVAILABLE(macos(10.10), ios(8.0), watchos(2.0), tvos(9.0));
/*!
@abstract In-memory capacity of the receiver.
@discussion At the time this call is made, the in-memory cache will truncate its contents to the size given, if necessary.
@result The in-memory capacity, measured in bytes, for the receiver.
*/
// 在进行此调用时,如有必要,内存缓存将将其内容截断为给定的大小。
// 属性返回的是接收者的内存容量,以字节为单位。
@property NSUInteger memoryCapacity;
/*!
@abstract The on-disk capacity of the receiver.
@discussion The on-disk capacity, measured in bytes, for the receiver. On mutation the on-disk cache will truncate its contents to the size given, if necessary.
*/
// 接收器的磁盘容量(以字节为单位)。 在变化时,如有必要,
// 磁盘缓存会将其内容截断为给定的大小
@property NSUInteger diskCapacity;
/*!
@abstract Returns the current amount of space consumed by the
in-memory cache of the receiver.
@discussion This size, measured in bytes, indicates the current
usage of the in-memory cache.
@result the current usage of the in-memory cache of the receiver.
*/
// 获取当前接收者消耗的内存缓存
@property (readonly) NSUInteger currentMemoryUsage;
/*!
@abstract Returns the current amount of space consumed by the
on-disk cache of the receiver.
@discussion This size, measured in bytes, indicates the current
usage of the on-disk cache.
@result the current usage of the on-disk cache of the receiver.
*/
// 获取当前接收者消耗的磁盘缓存
@property (readonly) NSUInteger currentDiskUsage;
@end
2. NSURLCache分类NSURLSessionTaskAdditions
下面我们就看一下该文档的API
@interface NSURLCache (NSURLSessionTaskAdditions)
// 存储指定task的响应缓存
- (void)storeCachedResponse:(NSCachedURLResponse *)cachedResponse forDataTask:(NSURLSessionDataTask *)dataTask API_AVAILABLE(macos(10.10), ios(8.0), watchos(2.0), tvos(9.0));
// 获取指定task的缓存数据,并给出数据回调
- (void)getCachedResponseForDataTask:(NSURLSessionDataTask *)dataTask completionHandler:(void (^) (NSCachedURLResponse * _Nullable cachedResponse))completionHandler API_AVAILABLE(macos(10.10), ios(8.0), watchos(2.0), tvos(9.0));
// 移除指定task的缓存
- (void)removeCachedResponseForDataTask:(NSURLSessionDataTask *)dataTask API_AVAILABLE(macos(10.10), ios(8.0), watchos(2.0), tvos(9.0));
@end
NSURLCache需求、使用场景和要点
1. 需求
- 在IOS应用程序开发中,为了减少与服务端的交互次数,加快用户的响应速度,一般都会在IOS设备中加一个缓存的机制。使用缓存的目的是为了使用的应用程序能更快速的响应用户输入,使程序高效的运行。有时候我们需要将远程web服务器获取的数据缓存起来,减少对同一个url多次请求。使用sdk中的
NSURLCache
类,可以很方便的实现此功能。 -
NSURLCache
可以做到完全的离线缓存,即在没有网络的情况下打开离线内容。通过自定义的实现,将缓存文件存放到沙盒路径下,缓存空间没有大小限制。可以借鉴H5离线缓存中的Manifest
文件,来定义缓存策略。Manifest文件从服务器端下载下来,在本地做版本对比,来实现存储和更新。 -
NSURLCache
拦截不到WKWebView
中发出的任何网络请求。所以如果使用WKWebView
的话,NSURLCache
实现不了离线缓存的功能。
2. 使用场景
-
NSURLRequest
需要一个缓存策略参数来说明它请求的url何如缓存数据的。
3. 要点
-
UIWebView
的的NSURLRequest
请求,以及自己用NSURLConnection发送的请求,NSURLCache都会拦截并存储。 - NSURLCache只对异步请求有效。
- NSURLCache的缓存包括内存缓存和磁盘缓存,iOS4.x系统只有内存缓存,iOS5.x及以上两者都有,但仅支持HTTP,HTTPS在iOS6中增加了支持。磁盘缓存有默认的缓存路径,也可以自己指定路径。
- 当系统存储空间不足时,当前的请求不会被缓存,包括之前的磁盘缓存也可能被系统清除掉。
- 如果有使用NSURLCache,在应用收到内存警告时,应该清空缓存:
removeAllCachedResponses
。 - 只能用在get请求里面,post可以洗洗睡了。
- 缓存机制选:
NSURLRequestReturnCacheDataElseLoad
有缓存从缓存取数据,没有缓存从网络取数据。 - 需要服务器定义数据是否发生变化,
allHeaderFields
里可以查找到是否修改了的信息。公司服务器没有定义的话,就不能够判断读取的缓存数据是否需要刷新。 - 原先网络请求的回调会被缓存结果代替,有缓存的情况下根本不会去网络获取数据,返回的都是缓存结果,除非服务器
allHeaderFields
数据发生了变化——-大坑,所以会变动的数据就尽量不要用这种方式请求,一般也应用于离线阅读,不会改变数据的地方。 - 删除缓存的
removeCachedResponseForRequest
这个方法是无效的,所以缓存是不会被删除的 —— 只有删除全部缓存才有效
自定义NSURLCache
在一些特殊场景,如果要实现自定义的缓存机制,需要子类化NSURLCache
。
-
重写
cachedResponseForRequest:(NSURLRequest *)request
,这个会在请求发送前会被调用,从中我们可以判定是否针对此NSURLRequest返回本地数据。如果本地没有缓存就调用下面这条语句:return [super cachedResponseForRequest:request];
。 -
重写
storeCachedResponse:(NSCachedURLResponse *)cachedResponse forRequest:(NSURLRequest *)request
,我们可以对某一个请求做我们自己的数据保存机制,如果使用系统默认的数据保存机制,则调用[super storeCachedResponse:cachedResponse forRequest:request];
。
参考文章
后记
本篇讲述了NSURLCache这个类的详细信息以及一些注意要点。