Music_Player3/MusicPlayer/MP/Common/Tool(工具封装)/MP_CacheManager.swift
2024-05-29 13:20:07 +08:00

144 lines
6.2 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// MP_CacheManager.swift
// MusicPlayer
//
// Created by Mr.Zhou on 2024/5/23.
//
import Foundation
///
class CachedMedia: NSObject, Codable {
//
let data: Data
//
let dataBlocks:[MediaDataBlock]
//
let isComplete: Bool
//
let maxCount:Int64
init(data: Data, dataBlocks:[MediaDataBlock], isComplete: Bool, maxCount:Int64) {
self.data = data
self.dataBlocks = dataBlocks
self.isComplete = isComplete
self.maxCount = maxCount
}
}
///
class MP_CacheManager {
// 访
static let shared = MP_CacheManager()
// 1videoID2
private let memoryCache = NSCache<NSString, CachedMedia>()
//
private let fileManager = FileManager.default
//
private let cacheDirectory: URL
//线
private var cacheQueue = DispatchQueue(label: "com.MP_CacheManager.cacheQueue")
//
private var cacheOperations: [String: DispatchWorkItem] = [:]
//
private let throttleInterval: TimeInterval = 1.0
//
private let expirationInterval: TimeInterval = 86400 // 24
private init() {
//
let urls = fileManager.urls(for: .cachesDirectory, in: .userDomainMask)
//
cacheDirectory = urls[0].appendingPathComponent("MyAssetCacheManager")
//
if !fileManager.fileExists(atPath: cacheDirectory.path) {
//
try? fileManager.createDirectory(at: cacheDirectory, withIntermediateDirectories: true, attributes: nil)
}
}
///
/// - Parameters:
/// - data:
/// - key: 使videoId
func cacheData(_ data: Data, dataBlocks:[MediaDataBlock], forKey key: String, isComplete: Bool = false, maxCount:Int64) {
// cacheQueue 线
cacheQueue.async { [weak self] in
// key
self?.cacheOperations[key]?.cancel()
//
let operation = DispatchWorkItem {
self?.performCacheData(data, dataBlocks: dataBlocks, forKey: key, isComplete: isComplete, maxCount: maxCount)
// cacheQueue
self?.cacheQueue.async {
self?.cacheOperations.removeValue(forKey: key)
}
}
// operation
self?.cacheOperations[key] = operation
// operation
self?.cacheQueue.asyncAfter(deadline: .now() + self!.throttleInterval, execute: operation)
}
}
//
private func performCacheData(_ data: Data, dataBlocks:[MediaDataBlock], forKey key: String, isComplete: Bool = false, maxCount:Int64) {
let contentToCache = CachedMedia(data: data, dataBlocks: dataBlocks, isComplete: isComplete, maxCount: maxCount)
memoryCache.setObject(contentToCache, forKey: key as NSString)
//
let fileURL = self.cacheDirectory.appendingPathComponent(key)
//
let tempURL = fileURL.appendingPathExtension("tmp")
let encoder = JSONEncoder()
do {
let newData = try encoder.encode(contentToCache)
//
try newData.write(to: tempURL, options: .atomicWrite)
//
if self.fileManager.fileExists(atPath: fileURL.path) {
try self.fileManager.removeItem(at: fileURL)
}
//
try self.fileManager.moveItem(at: tempURL, to: fileURL)
//
let expirationDate = Date().addingTimeInterval(self.expirationInterval)
try self.fileManager.setAttributes([.modificationDate: expirationDate], ofItemAtPath: fileURL.path)
} catch {
//
try? self.fileManager.removeItem(at: tempURL)
print("无法将密钥数据写入磁盘 \(key) - 错误: \(error)")
}
}
///
/// - Parameter key: 使videoId
/// - Returns:
func data(forKey key: String) -> CachedMedia? {
if let cachedContent = memoryCache.object(forKey: key as NSString){
return cachedContent
}
return cacheQueue.sync {
[weak self] in
guard let self = self else { return nil }
let fileURL = self.cacheDirectory.appendingPathComponent(key)
guard let jsonData = try? Data(contentsOf: fileURL) else { return nil }
// JSON CachedMedia
let decoder = JSONDecoder()
do{
let cachedContent = try decoder.decode(CachedMedia.self, from: jsonData)
//
let attributes = try fileManager.attributesOfItem(atPath: fileURL.path)
guard let modificationDate = attributes[.modificationDate] as? Date else { return nil }
if Date().timeIntervalSince(modificationDate) < expirationInterval{
//
memoryCache.setObject(cachedContent, forKey: key as NSString)
return cachedContent
} else {
//
try fileManager.removeItem(at: fileURL)
}
} catch {
print("读取缓存数据失败 \(key) - 错误: \(error)")
}
return nil
}
}
}