Open5
iOSアプリにおけるキャッシュ
キャッシュされたデータへのアクセス
- URL ローディングシステムは、メモリとディスクにレスポンスをキャッシュする
- 目的
- パフォーマンス向上
- ネットワークトラフィックの削減
NSURLRequest.CachePolicy
について
- キャッシュされたレスポンスとの相互作用を指定するための定数
- デフォルトは
useProtocolCachePolicy
実装方法
URLRequest
をインスタンス化するときにプロパティに渡す
let imageURL = ""
var request = URLRequest(url: imageURL, cachePolicy: .returnCacheDataElseLoad) // ここで指定する
URLConfiguration
をインスタンス化するときにプロパティに渡す
let config = URLSessionConfiguration.default
config.requestCachePolicy = .returnCacheDataElseLoad
キャッシュポリシー | ローカルのキャッシュ | サーバ |
---|---|---|
reloadIgnoringLocalCacheData |
無視する | 排他的にアクセスする |
returnCacheDataDontLoad |
排他的にアクセスする | 無視する |
returnCacheDataElseLoad |
初回に試す | 必要な時のみアクセスする |
useProtocolCachePolicy |
プロトコルによる | プロトコルによる |
useProtocolCachePolicy
が選択された場合のキャッシュのdecition tree
キャッシュに直接アクセスする方法
-
cachedResponse(for:)
を呼ぶ- キャッシュがあれば、
CachedURLResponse
オブジェクトが返る。なければnil
になる
- キャッシュがあれば、
キャッシュはどこにどのくらい保存されているのか
-
currentDiskCache
やcurrenctMemoryCache
を調べることで、キャッシュが使っているリソースがどこでどのくらいかを調べることができる
キャッシュを削除する方法
-
URLRequest
ごとに削除したい場合は、removeCachedResponse(for:)
- 特定の日付以降のキャッシュを削除したい場合は、
removeCachedResponse(since:)
- 全てのキャッシュを削除したい場合は、
removeAllCachedResponse()
キャッシュを手動でハンドリングする方法
- レスポンスごとにキャッシュの仕組みを管理したい場合に実装する
実装方法
-
URLSessionDataDelegate
プロトコルのurlSession(_:dataTask:willCacheResponse:completionHandler:)
を呼び出す -
completionHandler
に次のいずれかを渡して呼び出す必要がある-
CachedURLResponse
オブジェクト(提供されたオブジェクトproposedResponse
をそのままキャッシュする) -
niil
(キャッシュしない) - 自作した
CachedURLRequest
オブジェクト(storagePolicy
やuserInfo
をカスタマイズすることができる)
-
// 以下はhttpsできたレスポンスは、メモリ上でのキャッシュのみを許す実装
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask,
willCacheResponse proposedResponse: CachedURLResponse,
completionHandler: @escaping (CachedURLResponse?) -> Void) {
if proposedResponse.response.url?.scheme == "https" {
let updatedResponse = CachedURLResponse(response: proposedResponse.response,
data: proposedResponse.data,
userInfo: proposedResponse.userInfo,
storagePolicy: .allowedInMemoryOnly)
completionHandler(updatedResponse)
} else {
completionHandler(proposedResponse)
}
}
URLCache
について
-
URL リクエスト(
NSURLRequest
)と、キャッシュしたレスポンス(CachedURLResponse
)のオブジェクトをマップするためのオブジェクト -
iOSでは、アプリが起動していない時のみ、ディスク容量が少なくなると、ディスクのキャッシュを削除する
private let session: URLSession = {
let configuration = URLConfiguratio.default
let urlCache: URLCache = {
let memoryCapacity = 6 * 1024 * 1024 // 6MB
let diskCapacity = 6 * 1024 * 1024 // 6MB
let cacheDir = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first?.appendingPathComponent("\(Bundle.main.bundleIdentifier!)/hogehoge")
return URLCache(
memoryCapacity: memoryCapcity,
diskCapacity: diskCapacity,
directory: cacheDir
)()
}
configuration.urlCache = urlCache
let session = URLSession(configuration: configuration, delegate: nil, delegateQueue: nil)
return session
}()
キャッシュのディスクとメモリについて
SwiftUIにおける画像キャッシュ
AsyncImage は必要に応じて画像をキャッシュしているとのことだが、以下の記事によるとしていなそうとのこと。
以下のライブラリを参考に、自分でCachedAsyncImageを実装しても良さそうだし、このまま使っても良さそう
オフライン時の挙動