iOS - Cache 源码分析

Cache

Cache 提供了一个良好的公共 API,具有开箱即用的实现和出色的定制可能性。 Cache 利用 Swift 4中的 Codable 来执行序列化。

一、功能介绍

  • 使用 Swift 4 Codable。符合 Codable 任何内容都将由 Storage 轻松保存和加载。
  • 与内存和磁盘存储混合。
  • 通过 DiskConfig 和 MemoryConfig 许多选项。
  • 支持 expiry 和清理过期的对象。
  • 线程安全。 可以从任何队列访问操作。
  • 默认情况下同步。 还支持异步 API。
  • 广泛的单元测试覆盖率和出色的文档。
  • 支持iOS,tvOS和macOS。

二、安装

CocoaPods

在工程内 Podfile 文件中添加:

1
pod'Cache '

Carthage

在工程内 Cartfile 文件中添加:

1
github “ hyperoslo / Cache ”

您还需要在 copy-frameworks 脚本中添加 SwiftHash.framework 。

三、使用

存储

Cache 是基于责任链模式构建的,其中有许多处理对象,每个处理对象都知道如何执行 1 个任务并委托给下一个任务,因此您可以按照自己喜欢的方式编写存储。

目前支持以下存储

  • MemoryStorage :将对象保存到内存。
  • DiskStorage :将对象保存到磁盘。
  • HybridStorage :将对象保存到内存和磁盘,因此您可以在磁盘上获得持久化对象,同时在内存对象中快速访问。
  • SyncStorage :阻塞API,所有读写操作都在串行队列中调度,所有同步方式。
  • AsyncStorage :非阻塞API,操作在内部队列中进行调度以进行串行处理。 不应该同时进行读写操作。

虽然您可以自行决定使用这些存储,但您不必这样做。 因为我们还提供了一个方便的 Storage ,它使用了 HybridStorage ,同时通过 SyncStorage 和 AsyncStorage 公开同步和异步 API。

您需要做的就是使用 DiskConfig 和 MemoryConfig 指定所需的配置。 默认配置很好,但您可以自定义很多。

1
2
3
4
5
6
7
8
let diskConfig = DiskConfig(name: "Floppy")
let memoryConfig = MemoryConfig(expiry: .never, countLimit: 10, totalCostLimit: 10)

let storage = try? Storage(
diskConfig: diskConfig,
memoryConfig: memoryConfig,
transformer: TransformerFactory.forCodable(ofType: User.self) // Storage<User>
)

同步API

Storage 默认是同步的并且是 thread safe ,您可以从任何队列访问它。 所有同步功能都受 StorageAware 协议的约束。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Save to storage
try? storage.setObject(10, forKey: "score")
try? storage.setObject("Oslo", forKey: "my favorite city", expiry: .never)
try? storage.setObject(["alert", "sounds", "badge"], forKey: "notifications")
try? storage.setObject(data, forKey: "a bunch of bytes")
try? storage.setObject(authorizeURL, forKey: "authorization URL")

// Load from storage
let score = try? storage.object(forKey: "score")
let favoriteCharacter = try? storage.object(forKey: "my favorite city")

// Check if an object exists
let hasFavoriteCharacter = try? storage.existsObject(forKey: "my favorite city")

// Remove an object in storage
try? storage.removeObject(forKey: "my favorite city")

// Remove all objects
try? storage.removeAll()

// Remove expired objects
try? storage.removeExpiredObjects()

异步API

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
storage.async.setObject("Oslo", forKey: "my favorite city") { result in
switch result {
case .value:
print("saved successfully")
case .error(let error):
print(error)
}
}

storage.async.object(forKey: "my favorite city") { result in
switch result {
case .value(let city):
print("my favorite city is \(city)")
case .error(let error):
print(error)
}
}

storage.async.existsObject(forKey: "my favorite city") { result in
if case .value(let exists) = result, exists {
print("I have a favorite city")
}
}

storage.async.removeAll() { result in
switch result {
case .value:
print("removal completes")
case .error(let error):
print(error)
}
}

storage.async.removeExpiredObjects() { result in
switch result {
case .value:
print("removal completes")
case .error(let error):
print(error)
}
}

处理JSON响应

大多数情况下,我们的用例是从后端获取一些 json,在将 json 保存到存储器以供将来使用时显示它。 如果你使用像 Alamofire 或 Malibu 这样的库,你通常会以字典,字符串或数据的形式获得 json。

Storage 可以持久化 String 或 Data。您甚至可以使用JSONArrayWrapper 和 JSONDictionaryWrapper 将 json 保存到 Storage ,但我们更喜欢保留强类型对象,因为这些是您将用于在 UI 中显示的对象。 此外,如果 json 数据无法转换为强类型对象,那么保存它的重点是什么?

您可以在 JSONDecoder 上使用这些扩展来将 json 字典,字符串或数据解码为对象。

1
2
3
let user = JSONDecoder.decode(jsonString, to: User.self)
let cities = JSONDecoder.decode(jsonDictionary, to: [City].self)
let dragons = JSONDecoder.decode(jsonData, to: [Dragon].self)

使用 Alamofire 执行对象转换和保存的 Alamofire

1
2
3
4
5
6
7
8
Alamofire.request("https://gameofthrones.org/mostFavoriteCharacter").responseString { response in
do {
let user = try JSONDecoder.decode(response.result.value, to: User.self)
try storage.setObject(user, forKey: "most favorite character")
} catch {
print(error)
}
}
------本文结束 感谢阅读------

本文地址:http://kaaaaai.cn/articles/lean-cache.html
本文基于 知识共享署名-相同方式共享 4.0 国际许可协议发布
转载请注明出处,谢谢!

众筹项目:拯救世界!
0%