一个 Swift 库,用于将项目缓存到文件系统(默认使用 SQLite)。
PersistentCache
是缓存存储的一个视图,它使用特定类型的键和值。它将使用内存缓存来快速访问常用数据。并且由于内存缓存是类型特定的,因此它甚至可能比更通用的缓存实现更快。
PersistentCache
可以选择具有一个 CacheStorage
,它用于持久化数据,使其在应用程序启动之间,甚至在内存警告期间也能存在。默认情况下,这设置为共享的 SQLiteCacheStorage
。持久化存储使用 Codable
将所有键转换为字符串,并将所有值转换为数据。
缓存和存储是线程安全的。每个缓存都使用自己的串行队列,以便不同的缓存可以彼此独立运行,同时保持内部一致性。当缓存只需要访问其内存存储时,它可以与其他缓存并行进行。当它需要访问存储时,它将串行执行。尽可能多地异步完成工作。例如,当设置一个新值时,内存缓存会立即更新,以便后续对该数据的请求是正确的,但会异步写入磁盘。
struct Message: Codable {
var id: UUID = UUID()
var createdAt: Date = Date()
var body: String = ""
}
let cache = PersistentCache<UUID, [Message]>()
let roomID = UUID()
if let cached = cache[roomID] {
// show cached messages
} else {
// load them some expensive way
cache[roomID] = (0..<10).map({ Message(body: String($0)) })
}
通常您只需要指定键和值的类型。但是,您也可以包含缓存存储和命名空间。
let cache = PersistentCache<UUID, [Message]>(storage: customStorage, namespace: "com.example�.app")
使用自定义存储可能很有用,无论是使用不同的存储方法还是在缓存之间并行化存储。
命名空间对于避免多个缓存之间的名称冲突非常有用。
访问缓存数据的最简单方法是使用下标。
let value = cache[key]
cache[key] = value
如果可能,这将使用内存缓存,或者在需要时访问存储。
您也可以使用缓存项访问数据
let value = cache[item: key]
cache[item: key] = Item(value, expiresIn: 60 * 60)
这主要用于设置值的过期日期。常规下标将忽略过期的项目,因此在实践中,您应该很少需要直接获取项目。
存在各种获取方法来在缓存上执行查找或更新
cache.fetch(key, fallback: { value })
这是下标访问的基本包装器。其他获取方法异步执行查找。
cache.fetch(key, queue: .main) { value in
// use value (possibly nil)
}
cache.fetch(key, queue: .main, fallback: { value }) { value in
// use value (never nil)
}
这些方法将首先检查内存缓存中是否存在数据,如果存在,则立即调用完成,而无需调度到另一个线程。但是,如果需要,它们将在后台队列中异步地从存储加载数据。
为了测试和灵活性,在创建时传入缓存可能是一个好主意。
class Foo {
let cache: PersistentCache<UUID, String>?
init(cache: PersistentCache<UUID, String>? = PersistentCache(namespace: "Foo")) {
self.cache = cache
}
}
let fooA = Foo(cache: PersistentCache(storage: custom))
let fooA = Foo(cache: PersistentCache(storage: nil))
let fooB = Foo(cache: nil)
请注意,缓存是可选的。如果测试或框架的用户想要完全禁用缓存,他们可以为缓存传递 nil。或者要禁用持久化存储并仅使用内存缓存,他们可以传递一个没有后备存储的缓存。最后,如果他们想使用自定义存储方法,他们可以传递一个带有其特定存储类的缓存。