Vellum 1.2.3

Vellum 1.2.3

nayanda1 维护。



Vellum 1.2.3

  • nayanda

Vellum

build test Version License Platform

要求

  • 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 算法。它包含两种存储类型,即 内存存储磁盘存储。两种存储的大小都可以手动分配。

存储数据

alt text

  1. 存储数据到内存存储
  2. 如果内存存储已满,它将移除最久未访问的数据,直到有足够空间存储新数据
  3. 存储到内存中的数据
  4. 存储数据到磁盘存储
  5. 如果磁盘存储已满,它将移除最久未访问的数据,直到有足够空间存储新数据
  6. 存储到磁盘中的数据

获取数据

alt text

  1. 从内存存储中查找数据
  2. 如果数据存在,它将返回数据,并结束步骤
  3. 如果数据不在内存中,它将尝试从磁盘存储中查找数据
  4. 如果数据存在,它将数据存储到内存存储中以备将来快速使用,并返回数据并结束步骤
  5. 如果数据不存在,它将返回 nil

使用示例

基本使用

您只需要从工厂中获得ArchiveManager,并存储已实现ArchivableCodable的对象或使用相同的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?

上述代码将在第一次加载属性时尝试获取具有给定键的用户。