iOS URL Loading System包含如下:
官方文档参考
本文主要介绍三个部分:NSURLProtocol、Cookie Storage、Cache Management。
NSURLProtocol
NSURLProtocol参考链接
参考代码(增加对WKWebView的支持)
NSURLCache 和 NSCachedURLResponse
说完NSURLProtocol,就到了缓存阶段。
缓存管理类为对URL请求的回应提供了缓存。NSURLCache类为URL提供了通用缓存(这里注意,WKWebView从iOS9之后就有了WKWebsiteDataStore类来管理WKWebView http请求的缓存以及Cookie等)
- 调用[NSURLCache sharedURLCache]方法,默认会创建缓存区([NSURLCache sharedURLCache].currentDiskUsage = 86016Byte,[NSURLCache sharedURLCache].currentMemoryUsage = 0,iOS5之后默认是磁盘缓存),其中缓存区Memory capacity: 4 megabytes ,Disk capacity: 20 megabytes
- 当然我们也可以通过自定义的方式来实现是否缓存,感谢此链接。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
CusURLCache *cache = [[CusURLCache alloc] initWithMemoryCapacity:(2*1024*1024) diskCapacity:((100 * 1024 * 1024)) diskPath:nil];
[CusURLCache setSharedURLCache:cache];
return YES;
}
// CusURLCache.h
// Http测试
//
// Created by XinWeizhou on 2017/4/28.
// Copyright © 2017年 XinWeizhou. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface CusURLCache : NSURLCache
@end
#import "CusURLCache.h"
@implementation CusURLCache
// CusURLCache告诉系统我有怎样的已缓存的NSCachedURLResponse对象(或者没有),这里拦截了http://img1.gtimg.com/news/pics/hv1/138/183/2205/143426928.jpeg,并且做了假的NSURLResponse以供缓存
- (NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request {
NSURL *url = [request URL];
NSLog(@"request.string = %@",request.URL.absoluteString);
if ([url.absoluteString isEqualToString:@"http://img1.gtimg.com/news/pics/hv1/138/183/2205/143426928.jpeg"]) {
NSLog(@"request = %@",request);
NSURLResponse *response =
[[NSURLResponse alloc] initWithURL:url
MIMEType:@"text/plain"
expectedContentLength:1
textEncodingName:nil];
NSCachedURLResponse *cachedResponse =
[[NSCachedURLResponse alloc] initWithResponse:response
data:[NSData dataWithBytes:" " length:1]];
// 有人可能会认为只需要返回假的响应对象就够了,没必要缓存它。但这样会因响应对象被系统释放而导致app crash。不知道为何为会这样,可能是iOS的bug(Mac OS X 10.5.x也存在同样问题,而10.4.x及更早的系统上没有问题),也可能是URL Loading System内部类之间的依赖所致。
[super storeCachedResponse:cachedResponse forRequest:request];
}
return [super cachedResponseForRequest:request];
}
- (void)storeCachedResponse:(NSCachedURLResponse *)cachedResponse forRequest:(NSURLRequest *)request {
NSLog(@"request2 = %@ === response2 = %@",request,cachedResponse);
[super storeCachedResponse:cachedResponse forRequest:request];
}
说明:NSURLCache 将对每一个NSURLRequest对象遵守缓存策略(NSURLRequestCachePolicy),策略如下所示:
1. NSURLRequestUseProtocolCachePolicy 默认的缓存策略,对特定的URL请求使用网络协议中实现的缓存逻辑
2. NSURLRequestReloadIgnoringLocalCacheData 忽略本地缓存,重新请请求
3. NSURLRequestReloadIgnoringLocalAndRemoteCacheData 忽略本地和远程缓存,重新请求(未实现)
4. NSURLRequestReturnCacheDataElseLoad 有缓存则从中加载,如果没有则去请求
5. NSURLRequestReturnCacheDataDontLoad 无网络状态下不去请求,一直加载本地缓存数据无论其是否存在
6. NSURLRequestReloadRevalidatingCacheData 默从原始地址确认缓存数据的合法性之后,缓存数据才可使用,否则请求原始地址(未实现)
注意:NSURLCache缓存不缓存request及response,不是由request得缓存策略决定的,缓存策略只是说明是否加载已经存在的缓存,缓存机制有URL Loading System提供。
Cookie Storage
现在谈谈httpCookie相关:NSHTTPCookie和NSHTTPCookieStorage。(这里注意,WKWebView从iOS9之后就有了WKWebsiteDataStore类来管理WKWebView http请求的缓存以及Cookie等)
-
cookie和NSURLRequest的关系,除非NSURLRequest明确指定不使用cookie(HTTPShouldHandleCookies设为NO),否则URL loading
system会自动为NSURLRequest发送合适的存储cookie。 -
NSHTTPCookieStorage:从NSURLResponse返回的cookie也会根据NSHTTPCookieStorage的cookie访问策略(cookie acceptance policy)接收到系统中。
通过NSHTTPCookieStorage可读取/修改cookie接收策略,默认为NSHTTPCookieAcceptPolicyAlways.
-(NSHTTPCookieAcceptPolicy)cookieAcceptPolicy;
-(void)setCookieAcceptPolicy:(NSHTTPCookieAcceptPolicy)aPolicy.
一共有三种cookie accept policy。typedef enum {
NSHTTPCookieAcceptPolicyAlways,
NSHTTPCookieAcceptPolicyNever,
NSHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain
} NSHTTPCookieAcceptPolicy;NSHTTPCookieAcceptPolicyAlways:接收所有cookie,默认策略.
-
NSHTTPCookieStorage通知
当NSHTTPCookieStorage实例中的cookies变化时发出此通知
NSHTTPCookieManagerCookiesChangedNotification当NSHTTPCookieStorage实例的cookie acceptance policy变化时发出此通知
NSHTTPCookieManagerAcceptPolicyChangedNotification -
NSHTTPCookie
使用NSHTTPCookie的类方法可以将NSHTTPCookie实例与HTTP headerField相互转换:
// 从响应头获取Cookie信息:
+ (NSArray *)cookiesWithResponseHeaderFields:(NSDictionary *)headerFields forURL:(NSURL *)theURL;
// 手动cookie创建例子:
NSMutableDictionary *cookieProperties = [NSMutableDictionary dictionary]; // 创建cookie属性字典
[cookieProperties setObject:@"username" forKey:NSHTTPCookieName]; // 手动设置cookie的属性
[cookieProperties setObject:@"Boat" forKey:NSHTTPCookieValue];
[cookieProperties setObject:@"yzwind.com" forKey:NSHTTPCookieDomain];
[cookieProperties setObject:@"www.yzwind.com" forKey:NSHTTPCookieOriginURL];
[cookieProperties setObject:@"/" forKey:NSHTTPCookiePath];
[cookieProperties setObject:@"0" forKey:NSHTTPCookieVersion];
NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:cookieProperties];
// 用Cookie设置请求头:
NSDictionary * headers = [NSHTTPCookie requestHeaderFieldsWithCookies:@[cookie]];
// 请求头这里只设置了Cookie
request.allHTTPHeaderFields = headers;
打印结果
headers = {
Cookie = "username = Boat";
}
// 直接给请求头设置Cookie:
[request setValue:"username = Boat" forHTTPHeaderField:@"Cookie"];
网友评论