NamadaNativefier
NamadaNativiefier 是用于 iOS 的本地持久数据存储。这是我对旧库 iOSNativefier 的更新版本
示例
要运行示例项目,请先克隆仓库,然后从 Example 目录运行 pod install
要求
安装
NamadaNativefier 可以通过 CocoaPods 获取。要安装它,只需将以下行添加到你的 Podfile 中
pod 'NamadaNativefier'
作者
nayanda, [email protected]
许可协议
NamadaNativefier 在 MIT 许可协议下可用。更多信息请参阅 LICENSE 文件。
存储算法
NamadaNativefier 使用 LRU 算法。它包含两种存储类型:内存存储和磁盘存储。这两种存储的大小都可以手动指定。
存储数据
- 存储数据到内存存储
- 如果内存存储已满,它将删除最旧的访问数据,直到为新数据腾出足够的空间
- 存储到内存中的数据
- 存储数据到磁盘存储
- 如果磁盘存储已满,它将删除最旧的访问数据,直到为新数据腾出足够的空间
- 存储到磁盘中的数据
获取数据
- 从内存存储中查找数据
- 如果数据存在,它将返回数据并结束步骤
- 如果数据不在内存中,它将尝试从磁盘存储中查找数据
- 如果数据存在,它将数据存储到内存存储中以便将来更快地使用,并返回数据并结束步骤
- 如果数据不存在,它将返回 nil
使用示例
基本使用
NamadaNativefier 是为NamadaJSON设计的补充。您只需从工厂获取缓存管理器,并将实现 Archivable
、CodableArchivable
或 JSONArchivable
的对象存储起来即可。
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
,因为 CodableArchivable
是 Codable
和 Archivable
的 typealias,您的对象将自动具有那些方法。您只需添加您希望作为主键的 primaryKey
属性,只要该值是 String
。
struct User: CodableArchivable {
var primaryKey: String { userName }
var userName: String
var fullName: String
var age: Int
}
JSONArchivable
如果您的对象是 JSONAble
,只需添加 Archivable
或将 JSONAble
改为 JSONArchivable
,因为 JSONArchivable
是 JSONAble
和 Archivable
的 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()
匹配属性是否为nilisNotNil()
匹配属性不为nilcontains(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