账单表:Bill
字段 | 类型 | 说明 |
---|---|---|
billID | NSString | 账单ID,主键 |
date | NSString | 账单产生日期 |
money | Double | 账单金额 |
isIncome | Bool | true代表收入,false代表支出 |
remark | NSString | 备注 |
accountID | NSString | 账户ID外键 |
categoryID | NSString | 类别ID外键 |
bookID | NSString | 账本ID外键 |
</br> 账单类型表:Category
字段 | 类型 | 说明 |
---|---|---|
cateID | NSString | 账单类型ID,主键 |
name | NSString | 类型名 |
imageName | NSString | 图标名 |
isIncome | Bool | true代表收入,false代表支出 |
</br> 账户表:Account
字段 | 类型 | 说明 |
---|---|---|
accountID | NSString | 账户ID,主键 |
name | NSString | 类型名 |
money | Double | 账户余额 |
</br> 账本表:Book
字段 | 类型 | 说明 |
---|---|---|
bookID | NSString | 账本ID,主键 |
name | NSString | 账本名 |
</br> 以上,就是该项目的所有数据库表。实际项目会因业务需求,追加一些字段,但核心还是不变的。
Realm 是一个跨平台的移动数据库引擎,2014年7月发布,准确来说,它是专门为移动应用所设计的数据持久化解决方案之一。Realm可以轻松地移植到您的项目当中,并且绝大部分常用的功能(比如说插入、查询等等)都可以用一行简单的代码轻松完成!
Realm有如下特点:
官方api: https://realm.io/cn/docs/objc/latest/
</br> 在Realm数据库中,你不需要写任何的sql语句,只需将你的模型继承RLMObject,之后的事情就不需要再管了。 </br> 例如,账单表:
/// 账单模型
@interface MPBillModel : RLMObject
/// 账单ID
@property (nonatomic, copy) NSString *billID;
/// 账单产生日期,要跟recordDate区分开
@property (nonatomic, copy) NSString *dateStr;
/// 账单记录日期,指的是生成账单的时间,用于排序
@property (nonatomic, strong) NSDate *recordDate;
/// 是否为收入
@property (nonatomic, assign) BOOL isIncome;
/// 备注
@property (nonatomic, copy) NSString *remark;
/// 金额
@property (nonatomic, assign) double money;
/// 账单类别
@property (nonatomic, strong) MPCategoryModel *category;
/// 账户
@property (nonatomic, strong) MPAccountModel *account;
/// 账本
@property (nonatomic, strong) MPBookModel *book;
@end
RLM_ARRAY_TYPE(MPBillModel)
在.m文件中指定主键
#import "MPBillModel.h"
@implementation MPBillModel
+ (NSString *)primaryKey
{
return @"billID";
}
@end
</br>
在Realm中,你不需要写一句sql语句,即可完成增删查改。除了查询之外,“删增改”等写入操作必须开启事务,否则程序就会崩溃!
Realm查询支持以下三种方式: 1、使用断言字符串查询
/// 获得指定账本的所有账单
MPBookModel *book = [[MPBookManager shareManager] getCurrentBook];
RLMResults *results = [MPBillModel objectsWhere:@"book=%@", book];
2、使用 NSPredicate 查询:
/// 在指定账本,查询某个月份开头的账单
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"dateStr BEGINSWITH %@ and book.bookID=%@", dateStr, book.bookID];
RLMResults *results = [MPBillModel objectsWithPredicate:predicate];
3、链式查询 例如对插叙后的结果集进行排序,可以分以下两布
/// 获取当前账本的所有账单后,再排序
- (RLMResults *)getBillsInCurrentBook
{
MPBookModel *book = [[MPBookManager shareManager] getCurrentBook];
RLMResults *results = [MPBillModel objectsWhere:@"book=%@", book];
// 返回排序后的结果集
return [self sortTheResultsByDate:results];
}
/// 排序
- (RLMResults *)sortTheResultsByDate:(RLMResults *)results
{
// 首先根据dateStr(账单时间)进行排序
RLMSortDescriptor *desc1 = [RLMSortDescriptor sortDescriptorWithKeyPath:@"dateStr" ascending:NO];
// 再根据recordDate(记录时间)进行排序
RLMSortDescriptor *desc2 = [RLMSortDescriptor sortDescriptorWithKeyPath:@"recordDate" ascending:NO];
return [results sortedResultsUsingDescriptors:@[desc1, desc2]];
}
对Realm数据库进行写入操作时,必须开启事务。开启事务有以下两种方式:
1、分别调用开启和关闭事务
[realm beginWriteTransaction];
[realm commitWriteTransaction];
2、使用block
RLMRealm *realm = [RLMRealm defaultRealm];
[realm transactionWithBlock:^{
// 进行操作
}];
添加有两种方式
//1 、调用realm的addObject
RLMRealm *realm = [RLMRealm defaultRealm];
[realm transactionWithBlock:^{
// me是RLMObject
[realm addObject:me];
}];
//2、调用模型的createInDefaultRealmWithValue方法
[kRealm transactionWithBlock:^{
[MPBillModel createInDefaultRealmWithValue:bill];
}];
}
直接调用realm的deletObject方法
RLMRealm *realm = [RLMRealm defaultRealm];
[realm transactionWithBlock:^{
[realm deleteObject:bill];
}];
修改内容只要开启事务后,直接拿对象做操作即可
/// 将账单的金额改为999
RLMRealm *realm = [RLMRealm defaultRealm];
[realm transactionWithBlock:^{
bill.money = 999
}];
由于Realm是不支持ID自增的,如果要实现ID自增,需要自己实现,并且性能会不好。因此,在这里,我们需要给每一个字段创建一个独一无二的ID。 那么,我们可以通过NSUUID产生主键,方法如下:
// MyUtils.m
/**
创建主键
@return 主键
*/
+ (NSString *)createKey
{
NSUUID *uid = [NSUUID UUID];
return uid.UUIDString;
}
当你的数据模型发生变化时,需要调用以下代码进行数据库迁移。建议在AppDelegate中的 didFinishLaunchingWithOptions调用
/// 数据库版本检测
- (void)dbVersionCheck
{
RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
// 设置新的架构版本。这个版本号必须高于之前所用的版本号(如果您之前从未设置过架构版本,那么这个版本号设置为 0)
config.schemaVersion = 1;
// 设置闭包,这个闭包将会在打开低于上面所设置版本号的 Realm 数据库的时候被自动调用
config.migrationBlock = ^(RLMMigration *migration, uint64_t oldSchemaVersion) {
// 目前我们还未进行数据迁移,因此 oldSchemaVersion == 0
if (oldSchemaVersion < 1) {
// 什么都不要做!Realm 会自行检测新增和需要移除的属性,然后自动更新硬盘上的数据库架构
}
};
// 告诉 Realm 为默认的 Realm 数据库使用这个新的配置对象
[RLMRealmConfiguration setDefaultConfiguration:config];
// 现在我们已经告诉了 Realm 如何处理架构的变化,打开文件之后将会自动执行迁移
[RLMRealm defaultRealm];
}
Realm提供了一个专门用于查看Realm数据库的可视化工具---Realm Browse。在App Store即可进行下载~只需要打印出沙盒路径后,找到doucument下的realm文件即可查看。若查看失败,请留意一下Realm库的版本与Realm Browser的版本(一般最新的Realm库,需要新版的Realm Browser才能查看)。
这里写图片描述
在本文中,对项目所要使用的数据表列出来了,以及简单介绍了Realm的使用。建议大家在使用前建个小demo体验一下~