URL載入系統之五:快取、Cookies與協議

weixin_34239169發表於2018-01-03

快取

URL載入系統為請求提供了基於磁碟和記憶體的組合響應快取。這個快取讓應用減少了對網路連線的依賴,提高了效能。

一個NSURLRequest例項通過設定快取策略來指定本地快取。預設的快取策略是NSURLRequestUseProtocolCachePolicy,其行為是由協議指定的針對該協議最好的實現方式。另外幾種快取策略描述如下:

NSURLRequestReloadIgnoringCacheData:URL載入系統將從服務端載入資料,而完全忽略快取。

NSURLRequestReturnCacheDataElseLoad:URL載入系統使用快取資料,忽略其過期時間;只有在沒有快取版本的時候才從源端載入資料。

NSURLRequestReturnCacheDataDontLoad:允許應用指定只有在快取中的資料應該被返回。如果在建立NSURLConnection或NSURLDownload例項時使用這個快取策略,如果響應沒有在本地快取中,則直接返回nil。這類似於使用離線模式,且從來不進行網路連線。

需要注意的是,目前只有HTTP和HTTPS的響應還被快取。

快取最常用的場景是使用HTTP協議做網路請求,同時設定快取策略為NSURLRequestUseProtocolCachePolicy。如果一個請求的NSCachedURLResponse不存在,則載入系統會從源端獲取資料。如果請求的快取響應存在於本地,則URL載入系統檢查響應來確定它指定的內容必須被重新驗證。如果內容必須驗證,則載入系統發出一個HEAD請求到源端以確定資源是否已經改變。如果沒有改變,則URL載入系統返回快取響應物件。如果已經改變了,則URL載入系統從源端獲取資料。

如果快取響應物件沒有指定內容必須被重新驗證,則載入系統校驗快取響應物件的最大age或有效時間。如果快取物件未過期,則載入系統返回快取物件。如果響應過舊,則URL載入系統發起一個HEAD請求到源端檢視資源是否已被修改。如果修改了,則URL載入系統從源端獲取新的資料。否則,返回快取響應物件。

預設情況下,連線的資料基於請求的快取策略來進行快取,同時由處理請求的NSURLProtocol子類來解析。如果我們需要對快取做更精確的控制,我們可以實現一些代理方法來允許應用來確定請求是否應該快取:

對於NSURLSession資料和上傳任務,實現URLSession:dataTask:willCacheResponse:completionHandler:方法。這個代理方法只用於資料請求和上傳任務。而下載任務的快取由指定的快取策略來決定。

對於NSURLConnection,實現connection:willCacheResponse:方法

對於NSURLSession,我們的代理方法呼叫一個完成處理器block來告知會話需要快取什麼東西。對於NSURLConnection,代理方法返回連線需要快取的物件。不管是哪種情況,代理都會提供以下值之一:

允許快取的響應物件

新建立的響應物件,用於快取被修改的響應

NULL,以阻止快取

代理方法也可以提供與NSCacheURLResponse物件相關的userInfo字典,將這些物件作為響應的一部分儲存在快取中。

需要注意的是,如果我們使用NSURLSession眀實現了代理方法,則代理方法必須總是呼叫提供的完成處理器,否則會導致記憶體洩露。

Cookies

由於HTTP協議是無狀態的,客戶端通常使用cookie來提供URL請求間資料的持久化儲存。URL載入系統提供介面來建立和管理cookie,將cookie作為HTTP請求的一部分進行傳送,並在解析一個服務端的響應時獲取cookie。

NSHTTPCookie類封裝了一個cookie,並提供了大量訪問器來訪問cookie的各種屬性。該類同樣提供了方法用於HTTP cookie頭與NSHTTPCookie例項之間的互轉。URL載入系統自動傳送與NSURLRequest物件匹配的任何儲存的cookie,除非該請求指明不需要傳送cookie。同樣,NSURLResponse物件是返回的cookie將根據當前設定的cookie接收策略來處理。

NSHTTPCookieStorage提供介面來管理NSHTTPCookie物件的集合。與MacOS不同的是,iOS的cookie不能在應用間共享。NSHTTPCookieStorage允許一個應用指定cookie接收策略。

協議支援

URL載入系統允許客戶端程式擴充套件協議,以支援自定義的傳輸資料的方式。URL載入系統預設只支援http, https, file, ftp和data協議。

我們可以繼承NSURLProtocol來實現一個自定義的協議,然後使用NSURLProtocol類的的registerClass:方法將其註冊到URL載入系統中。當NSURLSession, NSURLConnection和NSURLDownload物件初始化一個NSURLRequest的連線時,URL載入系統以註冊順序的倒序來查詢每一個註冊類。每個類都將呼叫canInitWithRequest:方法,第一個返回YES的類將被用於處理請求。

如果自定義協議需要額外的屬性業支援請求與響應,則通過建立NSURLRequest, NSMutableRequest和NSResponse類的類別來提供這些屬性的訪問器。NSURLProtocol類提供方法在這些訪問器中設定和獲取屬性值。

URL載入系統負責在連線開始和完成時建立和釋放NSURLProtocol例項。我們的應用不應該直接建立NSURLProtocol的例項。

當NSURLProtocol子類通過URL載入系統初始化時,它提供了一個實現NSURLProtocolClient協議的客戶端物件。NSURLProtocol子類將訊息從NSURLProtocolClient協議傳送到客戶端物件,來告訴URL載入系統它建立了響應,接收資料,重定向到新的URL,請求認證,完成載入等操作。如果自定義協議支援認證,還必須實現NSURLAuthenticationChallengeSender協議。

相關文章