最近公司要缓存数据,本来开始想使用FMDB的,但是公司项目是swift的,而它是oc的,leader不同意,就推荐使用了CoreStore,它是swift出的框架,最新的已经支持到swift 5.0,它支持的版本有swift 3.2,swift 4.0 ,swift 5.0,文档也是比较全面,但是确实英文的,不提了,我太难了。
本文章,只面向实战,并不对
CoreStore里面的思想、模式、代码等做太多的解释。因为我也不懂,还没看。
image.png
我默认你已经会使用
cocopods,安装第三方库了。
以及一些CoreData的简单操作
NSPredicate的操作,本文也会设计一些,但是不会很多
1.创建一个CoreStore的数据库
create CoreData.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 参数对应的数据
configuration.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的其他写法,再次都不一一列举








网友评论