iOS URL Loading System包含如下:
官方文檔參考
本文主要介紹三個(gè)部分:NSURLProtocol莉兰、Cookie Storage、Cache Management革娄。
NSURLProtocol
NSURLProtocol參考鏈接
參考代碼(增加對WKWebView的支持)
NSURLCache 和 NSCachedURLResponse
說完NSURLProtocol擎宝,就到了緩存階段。
緩存管理類為對URL請求的回應(yīng)提供了緩存堡距。NSURLCache類為URL提供了通用緩存(這里注意,WKWebView從iOS9之后就有了WKWebsiteDataStore類來管理WKWebView http請求的緩存以及Cookie等)
- 調(diào)用[NSURLCache sharedURLCache]方法,默認(rèn)會創(chuàng)建緩存區(qū)([NSURLCache sharedURLCache].currentDiskUsage = 86016Byte羽戒,[NSURLCache sharedURLCache].currentMemoryUsage = 0缤沦,iOS5之后默認(rèn)是磁盤緩存),其中緩存區(qū)Memory capacity: 4 megabytes 易稠,Disk capacity: 20 megabytes
- 當(dāng)然我們也可以通過自定義的方式來實(shí)現(xiàn)是否緩存疚俱,感謝此鏈接。
- (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告訴系統(tǒng)我有怎樣的已緩存的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]];
// 有人可能會認(rèn)為只需要返回假的響應(yīng)對象就夠了,沒必要緩存它衬吆。但這樣會因響應(yīng)對象被系統(tǒng)釋放而導(dǎo)致app crash梁钾。不知道為何為會這樣,可能是iOS的bug(Mac OS X 10.5.x也存在同樣問題逊抡,而10.4.x及更早的系統(tǒng)上沒有問題)姆泻,也可能是URL Loading System內(nèi)部類之間的依賴所致。
[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 將對每一個(gè)NSURLRequest對象遵守緩存策略(NSURLRequestCachePolicy)冒嫡,策略如下所示:
1. NSURLRequestUseProtocolCachePolicy 默認(rèn)的緩存策略拇勃,對特定的URL請求使用網(wǎng)絡(luò)協(xié)議中實(shí)現(xiàn)的緩存邏輯
2. NSURLRequestReloadIgnoringLocalCacheData 忽略本地緩存,重新請請求
3. NSURLRequestReloadIgnoringLocalAndRemoteCacheData 忽略本地和遠(yuǎn)程緩存孝凌,重新請求(未實(shí)現(xiàn))
4. NSURLRequestReturnCacheDataElseLoad 有緩存則從中加載方咆,如果沒有則去請求
5. NSURLRequestReturnCacheDataDontLoad 無網(wǎng)絡(luò)狀態(tài)下不去請求,一直加載本地緩存數(shù)據(jù)無論其是否存在
6. NSURLRequestReloadRevalidatingCacheData 默從原始地址確認(rèn)緩存數(shù)據(jù)的合法性之后蟀架,緩存數(shù)據(jù)才可使用瓣赂,否則請求原始地址(未實(shí)現(xiàn))
注意:NSURLCache緩存不緩存request及response,不是由request得緩存策略決定的片拍,緩存策略只是說明是否加載已經(jīng)存在的緩存煌集,緩存機(jī)制有URL Loading System提供。
Cookie Storage
現(xiàn)在談?wù)刪ttpCookie相關(guān):NSHTTPCookie和NSHTTPCookieStorage捌省。(這里注意苫纤,WKWebView從iOS9之后就有了WKWebsiteDataStore類來管理WKWebView http請求的緩存以及Cookie等)
cookie和NSURLRequest的關(guān)系,除非NSURLRequest明確指定不使用cookie(HTTPShouldHandleCookies設(shè)為NO),否則URL loading
system會自動(dòng)為NSURLRequest發(fā)送合適的存儲cookie纲缓。-
NSHTTPCookieStorage:從NSURLResponse返回的cookie也會根據(jù)NSHTTPCookieStorage的cookie訪問策略(cookie acceptance policy)接收到系統(tǒng)中卷拘。
通過NSHTTPCookieStorage可讀取/修改cookie接收策略,默認(rèn)為NSHTTPCookieAcceptPolicyAlways.
-(NSHTTPCookieAcceptPolicy)cookieAcceptPolicy;
-(void)setCookieAcceptPolicy:(NSHTTPCookieAcceptPolicy)aPolicy.
一共有三種cookie accept policy色徘。typedef enum {
NSHTTPCookieAcceptPolicyAlways,
NSHTTPCookieAcceptPolicyNever,
NSHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain
} NSHTTPCookieAcceptPolicy;NSHTTPCookieAcceptPolicyAlways:接收所有cookie,默認(rèn)策略.
-
NSHTTPCookieStorage通知
當(dāng)NSHTTPCookieStorage實(shí)例中的cookies變化時(shí)發(fā)出此通知
NSHTTPCookieManagerCookiesChangedNotification當(dāng)NSHTTPCookieStorage實(shí)例的cookie acceptance policy變化時(shí)發(fā)出此通知
NSHTTPCookieManagerAcceptPolicyChangedNotification -
NSHTTPCookie
使用NSHTTPCookie的類方法可以將NSHTTPCookie實(shí)例與HTTP headerField相互轉(zhuǎn)換:
// 從響應(yīng)頭獲取Cookie信息:
+ (NSArray *)cookiesWithResponseHeaderFields:(NSDictionary *)headerFields forURL:(NSURL *)theURL;
// 手動(dòng)cookie創(chuàng)建例子:
NSMutableDictionary *cookieProperties = [NSMutableDictionary dictionary]; // 創(chuàng)建cookie屬性字典
[cookieProperties setObject:@"username" forKey:NSHTTPCookieName]; // 手動(dòng)設(shè)置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設(shè)置請求頭:
NSDictionary * headers = [NSHTTPCookie requestHeaderFieldsWithCookies:@[cookie]];
// 請求頭這里只設(shè)置了Cookie
request.allHTTPHeaderFields = headers;
打印結(jié)果
headers = {
Cookie = "username = Boat";
}
// 直接給請求頭設(shè)置Cookie:
[request setValue:"username = Boat" forHTTPHeaderField:@"Cookie"];