Skip to content

Instantly share code, notes, and snippets.

@liuzhida33
Created October 19, 2020 01:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save liuzhida33/6253cffa4492c9e1f495d3407f6c88ee to your computer and use it in GitHub Desktop.
Save liuzhida33/6253cffa4492c9e1f495d3407f6c88ee to your computer and use it in GitHub Desktop.
计算iOS常见缓存大小及清除缓存
import RxCocoa
import RxSwift
import Kingfisher
import NSObject_Rx
import WebKit
/// 缓存管理
final class CacheManager: HasDisposeBag {
/// 缓存类型
struct CacheType: OptionSet {
let rawValue: Int
static let picture = CacheType(rawValue: 1 << 0) /// 图片缓存
static let file = CacheType(rawValue: 1 << 1) /// 文件缓存
static let request = CacheType(rawValue: 1 << 2) /// 网络请求缓存
static let web = CacheType(rawValue: 1 << 3) /// web缓存
static let all: CacheType = [.picture, .file, .request, .web]
}
/// The default singleton instance.
static let shared = CacheManager()
private let cacheChanged = PublishSubject<Void>()
/// 返回某类型的缓存大小
///
/// - Parameter type: 缓存类型
/// - Returns: 缓存大小(单位MB)
func size(_ type: CacheType = .all) -> Observable<Double> {
return cacheChanged.startWith(())
.debounce(.milliseconds(250), scheduler: MainScheduler.instance)
.flatMap({ _ -> Observable<Double> in
return Observable.zip(type.helpers.map { $0.size() }).map { $0.reduce(0, { $0 + $1 }) / 1024 / 1024 }
})
.share(replay: 1)
}
/// 清理缓存
///
/// - Parameter type: 缓存类型
func clearDiskCache(_ type: CacheType = .all) {
Observable.zip(type.helpers.map { $0.clearCache() })
.flatMap { Observable.from($0) }
.bind(to: cacheChanged)
.disposed(by: disposeBag)
}
}
extension CacheManager.CacheType {
fileprivate var helpers: [CacheHelper] {
switch self {
case .picture: return [KingfisherCacheHelper()]
case .file: return [FileCacheHelper()]
case .request: return [RequestCacheHelper()]
case .web: return [WebCacheHelper()]
case .all: return [KingfisherCacheHelper(), FileCacheHelper(), RequestCacheHelper(), WebCacheHelper()]
default: return []
}
}
}
private protocol CacheHelper {
func calculateSize(completion handler: @escaping (Double) -> Void)
func clearCache(completion handler: (() -> Void)?)
}
extension CacheHelper {
func size() -> Observable<Double> {
return Observable.create({ observer -> Disposable in
self.calculateSize(completion: { size in
observer.onNext(size)
})
return Disposables.create()
})
}
func clearCache() -> Observable<Void> {
return Observable.create({ observer -> Disposable in
self.clearCache(completion: {
observer.onNext(())
})
return Disposables.create()
})
}
}
/// Kingfisher缓存
private struct KingfisherCacheHelper: CacheHelper {
func calculateSize(completion handler: @escaping (Double) -> Void) {
Kingfisher.ImageCache.default.calculateDiskStorageSize { result in
switch result {
case .success(let size):
handler(Double(size))
case .failure(let error):
handler(Double(0))
assertionFailure(error.localizedDescription)
}
}
}
func clearCache(completion handler: (() -> Void)?) {
Kingfisher.ImageCache.default.clearDiskCache {
handler?()
}
}
}
/// 下载文件缓存
private struct FileCacheHelper: CacheHelper {
func calculateSize(completion handler: @escaping (Double) -> Void) {
FileHelper.shared.calculateDiskStorageSize { result in
switch result {
case .success(let size):
handler(Double(size))
case .failure(let error):
handler(Double(0))
assertionFailure(error.localizedDescription)
}
}
}
func clearCache(completion handler: (() -> Void)?) {
FileHelper.shared.clearDiskCache {
handler?()
}
}
}
/// 网络缓存
private struct RequestCacheHelper: CacheHelper {
func calculateSize(completion handler: @escaping (Double) -> Void) {
handler(Double(URLCache.shared.currentDiskUsage))
}
func clearCache(completion handler: (() -> Void)?) {
URLCache.shared.removeAllCachedResponses()
handler?()
}
}
/// web缓存
private struct WebCacheHelper: CacheHelper {
func calculateSize(completion handler: @escaping (Double) -> Void) {
handler(0)
}
func clearCache(completion handler: (() -> Void)?) {
WKWebsiteDataStore.default().removeData(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes(), modifiedSince: Date(timeIntervalSince1970: 0)) {
handler?()
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment