NamadaNativefier 0.1.0

NamadaNativefier 0.1.0

nayanda1 维护。



  • nayanda

NamadaNativefier

NamadaNativiefier 是用于 iOS 的本地持久数据存储。这是我对旧库 iOSNativefier 的更新版本

CI Status Version License Platform

示例

要运行示例项目,请先克隆仓库,然后从 Example 目录运行 pod install

要求

安装

NamadaNativefier 可以通过 CocoaPods 获取。要安装它,只需将以下行添加到你的 Podfile 中

pod 'NamadaNativefier'

作者

nayanda, [email protected]

许可协议

NamadaNativefier 在 MIT 许可协议下可用。更多信息请参阅 LICENSE 文件。

存储算法

NamadaNativefier 使用 LRU 算法。它包含两种存储类型:内存存储和磁盘存储。这两种存储的大小都可以手动指定。

存储数据

  1. 存储数据到内存存储
  2. 如果内存存储已满,它将删除最旧的访问数据,直到为新数据腾出足够的空间
  3. 存储到内存中的数据
  4. 存储数据到磁盘存储
  5. 如果磁盘存储已满,它将删除最旧的访问数据,直到为新数据腾出足够的空间
  6. 存储到磁盘中的数据

获取数据

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

使用示例

基本使用

NamadaNativefier 是为NamadaJSON设计的补充。您只需从工厂获取缓存管理器,并将实现 ArchivableCodableArchivableJSONArchivable 的对象存储起来即可。

let cache = try! NativefierFactory.shared.cache(
    for: MyArchivable.self,
    initialMaxMemorySize: 10.megaByte, 
    initialMaxDiskSize: 20.megaByte
)

// will insert object
cache.insert(myObject)

let object = cache.get(objectWithKey: "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
    }
}

CodableArchivable

如果您的对象是 Codable,只需添加 Archivable 或将 Codable 改为 CodableArchivable,因为 CodableArchivableCodableArchivable 的 typealias,您的对象将自动具有那些方法。您只需添加您希望作为主键的 primaryKey 属性,只要该值是 String

struct User: CodableArchivable {
    var primaryKey: String { userName }
    var userName: String
    var fullName: String
    var age: Int
}

JSONArchivable

如果您的对象是 JSONAble,只需添加 Archivable 或将 JSONAble 改为 JSONArchivable,因为 JSONArchivableJSONAbleArchivable 的 typealias,您的对象将自动具有那些方法。您只需添加属性您希望作为主键的 @PKMapping 属性,只要该值是 JSONParseable。键将是属性的字符串版本。

class User: JSONArchivable {
    @PKMapping var userName: String = ""
    @AutoMapping var fullName: String = ""
    @AutoMapping var age: Int = 0
}

JSONArchivable 在其他方法中有一个优势,即它会自动更新实现 JSONArchivable 的属性,如果它独立更新。

// user is JSONArchivable
userCache.insert(user)

// shop is JSONArchivable
user.shop.imageUrl = updatedUrl
shopCache.insert(user.shop)

let userInCache = userCache.get(objectWithKey: user.primaryKey)
// will print true since the cache will be updated
print(user.shop.imageUrl == userInCache.shop.imageUrl)

CacheManager

要获取CacheManager,您可以使用NativefierFactory。您可以分配内存大小和磁盘大小的最大字节数。但请注意,该大小仅适用于第一次创建的CacheManager,如果缓存管理器已创建,则内存大小和磁盘大小与创建CacheManager时使用的第一次相同。如果您未指定内存大小或磁盘大小,它将使用默认值,即内存为1兆字节,磁盘为2兆字节。

let cache = try! NativefierFactory.shared.cache(
    for: User.self, 
    initialMaxMemorySize: 10.kiloByte, 
    initialMaxDiskSize: 20.kiloByte
)

// or not explicit
let cache: CacheManager<User> = try! NativefierFactory.shared.cache( 
    initialMaxMemorySize: 10.kiloByte, 
    initialMaxDiskSize: 20.kiloByte
)

缓存管理器有一些可用的方法和属性,包括

  • var maxSize: Int { get} 获取缓存的最多大小
  • var currentSize: Int { get} 获取当前已使用的缓存大小
  • func latestAccessedTime(for key: String) -> Date? 获取与相同键的对象最后一次访问的最新时间
  • func removeAllInvalidateObject(invalidateTimeInterval: TimeInterval) 删除超过时间间隔的所有对象
  • func insert(_ object: Archive) 插入对象
  • func update(_ object: Archive) 更新现有对象,如果没有则插入
  • func get(objectWithKey key: String) -> Archive? 获取给定键的对象
  • func getAll(limitedBy limit: Int) -> [Archive] 获取限制为limit的所有对象
  • func getAll() -> [Archive] 获取缓存的全部对象
  • func process(queries: [QueryCompatible]) -> [Archive] 处理查询。这将在以后讨论
  • func delete(objectWithKey key: String) 删除给定键的对象
  • func clear() 从缓存中删除所有对象

Query

您可以从缓存中进行查询。有3种类型的查询

  • QueryFinder 通过属性查找对象/结果
  • QuerySorter 根据属性排序结果
  • QueryLimiter 限制结果量

所有查询都可以组合使用,类似于AND条件

let results = userCache.findWhere
    .userName(contains("premium"))
    .fullName(isNotNil())
    .getResults()

上面的代码将找到缓存中所有用户名包含"premium"且fullName不为null的用户。结果是User的数组

let results = userCache.allSortedBy
    .age(.ascending)
    .fullName(.descending)
    .getResults()

上面的代码将根据用户的年龄和fullName(按降序排序)对缓存中的所有用户进行排序。结果是已排序的User数组

您还可以添加限制

let results = userCache.allSortedBy
    .age(.ascending)
    .fullName(.descending)
    .limit(by: 10)
    .getResults()

上面的代码将限制结果最多10个

您甚至可以结合查询

let results = userCache.findWhere
    .userName(contains("premium"))
    .fullName(isNotNil())
    .sortedBy
    .age(.ascending)
    .fullName(.descending)
    .limit(by: 10)
    .getResults()

上面的代码将找到缓存中所有用户名包含"premium"且fullName不为null的用户,然后按照年龄升序和fullName降序进行排序。结果限制为10。

以下是可用于QueryFinder的查找器列表

  • isNil() 匹配属性是否为nil
  • isNotNil() 匹配属性不为nil
  • contains(with: ) 匹配字符串属性是否包含给定的字符串
  • matches(withRegex: ) 若字符串属性匹配给定的正则表达式
  • contains(_: ) 若集合属性包含给定的元素
  • contains(atLeastOne: ) 若集合属性包含给定的任一元素
  • contains(all: ) 若集合属性包含所有给定的元素
  • countEqual(with: ) 若集合属性计数与给定数字相等
  • countGreater(than: ) 若集合属性计数大于给定数字
  • countLess(than: ) 若集合属性计数小于给定数字
  • countGreaterThanOrEqual(with: ) 若集合属性计数大于或等于给定数字
  • countLessThanOrEqual(with: ) 若集合属性计数小于或等于给定数字
  • equal(with: ) 若属性等于给定值
  • notEqual(with: ) 若属性不等于给定值
  • greater(than: ) 若属性大于给定值
  • less(than: ) 若属性小于给定值
  • greaterThanOrEqual(with: ) 若属性大于或等于给定值
  • lessThanOrEqual(with: ) 若属性小于或等于给定值

如果您想手动验证,可以使用 valid(with validator: (Property) -> Bool)

let results = userCache.findWhere
    .userName(valid(with: { $0.contains("premium") }))
    .getResults()

贡献

您知道怎么做的,只需克隆并提交 pull request