Vellum
要求
- Swift 5.0 或更高版本
- iOS 9.3 或更高版本
安装
CocoaPods
Vellum 可通过 CocoaPods 获得。要安装它,只需将以下行添加到您的 Podfile 中即可
pod 'Vellum'
Swift Package Manager
首先,创建一个名为 Package.swift 的文件,并添加此 GitHub 网址。它应如下所示
dependencies: [
.package(url: "https://github.com/nayanda1/Vellum.git", from: "1.2.0")
]
然后在您使用之前运行 swift build
以构建依赖项
作者
Nayanda Haberty, [email&protected]
许可协议
Vellum 在 MIT 许可协议下可用。更多信息请参阅 LICENSE 文件。
存储算法
Vellum 使用 LRU 算法。它包含两种存储类型,即 内存存储
和 磁盘存储
。两种存储的大小都可以手动分配。
存储数据
- 存储数据到内存存储
- 如果内存存储已满,它将移除最久未访问的数据,直到有足够空间存储新数据
- 存储到内存中的数据
- 存储数据到磁盘存储
- 如果磁盘存储已满,它将移除最久未访问的数据,直到有足够空间存储新数据
- 存储到磁盘中的数据
获取数据
- 从内存存储中查找数据
- 如果数据存在,它将返回数据,并结束步骤
- 如果数据不在内存中,它将尝试从磁盘存储中查找数据
- 如果数据存在,它将数据存储到内存存储中以备将来快速使用,并返回数据并结束步骤
- 如果数据不存在,它将返回 nil
使用示例
基本使用
您只需要从工厂中获得ArchiveManager
,并存储已实现Archivable
和Codable
的对象或使用相同的typealias
ArchiveCodable
。
let archives = try! ArchivesFactory.shared.archives(
for: MyArchivable.self,
trySetMaxMemorySize: 10.megaByte,
trySetMaxDiskSize: 20.megaByte
)
// will insert object
archives.record(myObject)
let object = archives.access(archiveWithKey: "object_key")
Archivable
Archivable
实际上是一个协议,它具有将对象转换为数据或将数据转换为对象的方法。同时,Archivable
还确保对象有键。
class User: Archivable {
var primaryKey: String { userName }
var userName: String = ""
var fullName: String = ""
var age: Int = 0
func archive() throws -> Data {
// do something to convert the object to Data
}
static func deArchive(fromData data: Data) throws -> Archivable {
// do something to convert the data to object
}
}
ArchiveCodable
如果您的对象是Codable
,只需添加Archivable
或使用相同的typealias
ArchiveCodable
,您的对象将自动拥有这些方法。您只需要添加您想要作为主键的primaryKey
属性,只要该值是String
即可。
struct User: Codable, Archivable {
var primaryKey: String { userName }
var userName: String
var fullName: String
var age: Int
}
ArchiveManager
要获取ArchiveManager
,可以使用ArchivesFactory
。您可以分配内存和磁盘大小的最大字节数。但请注意,大小仅在第一次创建ArchiveManager
时适用。如果缓存管理器已经创建,则内存大小和磁盘大小将被忽略。如果不分配内存大小或磁盘大小,则将使用默认值,即内存大小为1兆字节,磁盘大小为2兆字节。
let archives = try! ArchivesFactory.shared.archives(
for: User.self,
trySetMaxMemorySize: 10.kiloByte,
trySetMaxDiskSize: 20.kiloByte
)
// or not explicit
let sameArchives: ArchiveManager<User> = try! ArchivesFactory.shared.archives(
trySetMaxMemorySize: 10.kiloByte,
trySetMaxDiskSize: 20.kiloByte
)
ArchiveManager
有一些可以使用的方法和属性,例如:
var maxSize: Int { get }
用于获取缓存的最大大小var currentSize: Int { get }
用于获取当前使用的缓存大小func latestAccessedTime(for key: String) -> Date?
用于获取具有相同键的对象的最新访问时间func deleteAllInvalidateArchives(invalidateTimeInterval: TimeInterval)
用于移除所有超过时间间隔的对象func record(_ object: Archive)
用于插入对象func update(_ object: Archive)
用于更新现有对象,如果不存在则插入func access(archiveWithKey key: String) -> Archive?
用于获取具有给定键的对象func accessAll(limitedBy limit: Int) -> [Archive]
用于获取受限制的对象func accessAll() -> [Archive]
用于获取存储在缓存中的所有对象func delete(archiveWithKey key: String)
用于删除具有给定键的对象func deleteAll()
用于从缓存中删除所有对象func process(queries: [Query<Archive>]) -> [Archive]
用于处理查询。稍后将讨论此功能
查询
您可以从缓存中执行查询。有三种类型的查询:
QueryFinder
通过属性查找对象/结果QuerySorter
通过属性对结果进行排序QueryLimiter
限制结果
所有查询可以组合并按顺序执行
let results = userCache.findWhere { archive in
archive.userName(.contains("premium"))
.fullName(.isNotEqual(nil))
}
.getResults()
上述代码将查找所有用户缓存,用户名包含"premium"且全名不为空的结果。结果是用户数组
let results = userCache.sorted { by in
by.age(.ascending)
.fullName(.descending)
}
.getResults()
上述代码将获取所有用户缓存并按其年龄和全名降序排列。结果是已排序的用户数组
您还可以添加限制
let results = userCache.sorted { by in
by.age(.ascending)
.fullName(.descending)
}
.limitResults(by: 10)
.getResults()
上述代码将限制结果最多为10个
您甚至可以将查询组合起来
let results = userCache.findWhere { archive in
archive.userName(.contains("premium"))
.fullName(.isNotEqual(nil))
}
.sorted { by in
by.age(.ascending)
.fullName(.descending)
}
.limitResults(by: 10)
.getResults()
上述代码将查找所有用户缓存,用户名包含"premium"且全名不为空,然后按年龄升序和全名降序排序。结果限制为10个。
以下是可与 QueryFinder
一起使用的查找器列表:
contains(string: )
如果字符串属性包含给定字符串则匹配matches(regex: )
如果字符串属性与给定正则表达式匹配则匹配contains(with: )
如果集合属性包含给定元素则匹配contains(atLeastOne: )
如果集合属性包含至少一个给定元素则匹配contains(all: )
如果集合属性包含所有给定元素则匹配countEqual(with: )
如果集合属性计数等于给定数量则匹配countGreater(than: )
如果集合属性计数大于给定数量则匹配countLess(than: )
如果集合属性计数小于给定数量则匹配countGreaterOrEqual(with: )
如果集合属性计数大于或等于给定数量则匹配countLessOrEqual(with: )
如果集合属性计数小于或等于给定数量则匹配isEqual(with: )
如果属性等于给定值isNotEqual(with: )
如果属性不等于给定值greater(than: )
如果属性大于给定值less(than: )
如果属性小于给定值greaterOrEqual(with: )
如果属性大于或等于给定值lessOrEqual(with: )
如果属性小于或等于给定值
如果您想手动验证,可以使用 isValid(_ validator: (Property) -> Bool)
let results = userCache.findWhere { archive in
archive.userName(.isValid { $0.contains("premium") })
}
.getResults()
属性包装器
您可以使用Archived
属性包装器来包装任何属性,如果分配了属性,它将自动将其存储到ArchiveManager
@Archived var user: User?
如果要使属性基于给定的主键具有初始值,只需传递该键即可
@Archived(initialPrimaryKey: "some") var user: User?
上述代码将在第一次加载属性时尝试获取具有给定键的用户。