PersistentCacheKit

一个 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。或者要禁用持久化存储并仅使用内存缓存,他们可以传递一个没有后备存储的缓存。最后,如果他们想使用自定义存储方法,他们可以传递一个带有其特定存储类的缓存。