最近公司要缓存数据,本来开始想使用FMDB的,但是公司项目是swift
的,而它是oc
的,leader
不同意,就推荐使用了CoreStore,它是swift
出的框架,最新的已经支持到swift 5.0
,它支持的版本有swift 3.2
,swift 4.0
,swift 5.0
,文档也是比较全面,但是确实英文的,不提了,我太难了。
本文章,只面向实战,并不对
CoreStore
里面的思想、模式、代码等做太多的解释。因为我也不懂,还没看。
![](https://img.haomeiwen.com/i1773988/2fb83450a3f5e6b7.png)
我默认你已经会使用
cocopods
,安装第三方库了。
以及一些CoreData
的简单操作
NSPredicate
的操作,本文也会设计一些,但是不会很多
1.创建一个CoreStore
的数据库
![](https://img.haomeiwen.com/i1773988/98f95a9703f92836.png)
剩下的就是创建你需要的表,以及创建里面的字段,再次都不一一列举,如果不会,请右转百度,左转谷歌
2.使用CoreStore
连接次数据库
2.1 初始化一个默认的
dataStore
,会默认创建一个默认的SQLiteStore
try? CoreStoreDefaults.dataStack.addStorageAndWait()
2.2,我们也是可以 自定义库的
/**
xcodeModelName: 表示本地CoreData的名称
bundle: 表示CoreData所在的bundle
*/
let dataStack = DataStack(xcodeModelName: "CoreStore", bundle: Bundle.main, migrationChain: [])
dataStack.addStorage(
/*
fileName 表示本地保存的sql的名称,默认是Target的名称
configuration CoreData的组
**/
SQLiteStore(fileName: "CoreStoreDemo.sqlite",configuration: "Default", localStorageOptions: .recreateStoreOnModelMismatch), completion: {_ in })
/// 将创建的stack赋值给全局变量,那样我们就可以在任何地方去使用了,而不用再次创建
CoreStoreDefaults.dataStack = dataStack
configuration 参数对应的数据
![](https://img.haomeiwen.com/i1773988/cfbc455995d4f4ce.png)
3.添加数据
数据的操作,
CoreStore
使用的是同个方法
/**
异步执行的方法
asynchronous: 里面去执行添加,更新,删除,查询等数据的操作
completion:是执行的操作,成功或者失败的后续,如果你不想判断成功或者失败,你就使用下面那个方法,此方法的内部也是调用了下面方法
*/
CoreStoreDefaults.dataStack.perform(asynchronous: nil, completion: nil)
CoreStoreDefaults.dataStack.perform(asynchronous: nil, success: nil, failure: nil)
/*
同步执行的操作
synchronous: 里面去执行添加,更新,删除,查询等数据的操作
waitForAllObservers: 是个bool值,默认是`true`,当为`true`的时候,表示会通知所有的监听者发生改变后,再回返回,也造成一定的死锁,当设置为`false`的时候,是不告诉监听着,直接返回,会降低一些死锁的方式
**/
CoreStoreDefaults.dataStack.perform(synchronous: nil, waitForAllObservers: Bool)
/// 方法一
/**异步执行,可以在里面创建,更新,删除操作**/
CoreStoreDefaults.dataStack.perform(asynchronous: { transaction in
let student = transaction.create(Into<Student>())
student.name = faker.name.name()
student.score = Int16(faker.number.randomInt())
student.grade = [Int16(1),Int16(2)].randomElement()!
}, completion: { _ in })
/// 方法二
/**同步执行,可以在里面创建,更新,删除操作,
waitForAllObservers,默认是true,会通知完所有的监听着,再返回,有可能会造成死锁(监听里面也更新等)。
如果为false,则不会通知监听着,直接返回,减小死锁的概率
**/
do {
try CoreStoreDefaults.dataStack.perform(synchronous: { (transaction) in
let student = transaction.create(Into<Student>())
student.name = faker.name.name()
student.score = Int16(faker.number.randomInt())
student.grade = [Int16(1),Int16(2)].randomElement()!
}, waitForAllObservers: false)
} catch let error {
print("waitForAllObservers:",error.localizedDescription)
}
4.查询数据
查询数据库,有以下两个方法,同样的使用的方法也是上面介绍的两个方法操作的
/// 查询符合条件的所有数据,返回的是个`Array`
transaction.fetchAll()
/// 查询符合条件的单个数据,返回的是一个单独的对象
transaction.fetchOne()
/// 查询所有的strudent
CoreStoreDefaults.dataStack.perform(asynchronous: { (transaction) in
let students = try transaction.fetchAll(From<Student>())
for student in students {
print("student.name:", student.name!,"student.score:", student.score)
}
}, success: { _ in }, failure: { _ in })
/// 查询单个的`Student`
CoreStoreDefaults.dataStack.perform(asynchronous: { (transaction) -> Student? in
let student = try transaction.fetchOne(From<Student>())
print("student.name:", student!.name!,"student.score:", student!.score)
return student
}) { (result) in
switch result {
case .success(let student):
print("success,student.name:", student!.name!,"student.score:", student!.score)
case .failure(let error):
print("completion error :",error.localizedDescription)
}
}
4.1.条件where
语句的查询
CoreStore
是封装与CoreData
的,所以使用的是NSPredicate
来当条件语句查询的
where 基本介绍
and
或&&
且的关系or
或||
或的关系not
或!
非的关系
/// 下面这几种写法都是可以的,其实Where的本质还是封装的NSPredicate
/// 简单介绍一些 %K 表示 key, %@表示value
/// 相当于 name = Katlynn Dickens
let predicate = NSPredicate(format: "%K = %@", "name", "Katlynn Dickens")
let student = try transaction.fetchOne(From<Student>(), Where<Student>(predicate))
let student = try transaction.fetchOne(From<Student>(), Where<Student>("%K = %@", "name", "Katlynn Dickens"))
let student = try transaction.fetchOne(From<Student>().where(format: "%K = %@", "name", "Katlynn Dickens"))
4.2 排序
排序使用的关键词是
orderBy
.descending(\.score)
根据score
倒序排序
.ascending(\.score)
根据score
正序排序
let students = try transaction.fetchAll(From<Student>().orderBy(.ascending(\.score)))
let students = try transaction.fetchAll(From<Student>().orderBy(.descending(\.score)))
4.3分页查询
分页查询可是使用
tweak
配合fetchLimit 和 fetchOffset
来使用
/// fetchLimit 查询多少条
/// fetchOffset 间隔多少条,开始取值
let students = try transaction.fetchAll(From<Student>().orderBy(.descending(\.score)).tweak {
$0.fetchLimit = 1
$0.fetchOffset = 2
})
4.4 Select
的使用
- 当我们只需要一条数据中某一个属性值的时候,你还在
fetchOne
来获取数据,拿取值嘛?其实不需要。我们可以使用queryValue
配合select
即可- 当我们需要一些原始属性的时候,我们可以使用
queryAttributes
配合select
来获取原始属性数组select
都是可以可以配合where
、orderBy
、tweak
、GroupBy
配合使用到,再次都不一一列举了。
/// 当我们只需要一个参数值的时候,可以使用此方法
try CoreStoreDefaults.dataStack.queryValue(From<Student>(), Select<Student,Int16>("score"))
/// 在此方法上面我们还可以使用一些聚合函数
try CoreStoreDefaults.dataStack.queryValue(From<Student>(), Select<Student,Int16>(.count("score")))
/// 获取原始属性,只有name,score连个属性
/// 返回是一个包含符合条件的`字典数组`
try CoreStoreDefaults.dataStack.queryAttributes(From<Student>().select(Select("name", "score")))
//// 同样的再次方法里面我们也可以使用聚合函数
/// 并且使用了聚合函数的别名 as:
try CoreStoreDefaults.dataStack.queryAttributes(From<Student>().select(Select("name", .average("score", as: "scoreSum"))))
聚合函数,注意:我们可以使用
as:
来个聚合函数别名
.average
平均数.sum
和count
个数maximum
最大值minimum
最小值
注意,以上的orderBy
分页
、select
都是可以使用类似where
的其他写法,再次都不一一列举
网友评论