昨天跟几个哥们儿吃饭, 大家聊到数据库, 也谈到了 FMDB 和 CoreData 的优缺点, 突然发现 CoreData 我只记得个大概了, 其实除了 FMDB 和 CoreData, 还有一种常用的数据库是 Realm数据库.
FMDB 操作的是 SQLite 数据库, CoreData 底层其实也是操作 SQLite 数据库, 只是 CoreData 不需要写 SQL 语句,而且 CoreData 是存储 OC 对象的.
Realm 也是存储对象的, 而且用法比较简单. 也不失为除 FMDB 和 CoreData 的另外一个选择, 遇到没听过这个的也可以装个 X
我们今天来用 Realm 数据库做一个简单的通讯录
- 要使用 Realm 数据库, 首先要导入 Realm.framework 这个框架, 从Realm官网上可以下载,我使用的是realm-objc-2.0.3 这个版本, 下载解压完成后, 将iOS文件夹中的 static文件中的静态库拖到工程中
- 然后点击 Targets, 选择工程, 点击 Build Phases, 添加libz.tbd 和 libc++.tbd 两个库
- 点击 plugin 文件中的项目, 运行,然后退出 XCode, 重启 XCode, 就可以安装成功插件, 我们就可以利用插件自动生成模型类
安装成功插件后, 我们 command + N 在新建文件的时候就可以找到这么个东东
Realm Model Object- Realm Model Object, 顾名思义, 就是Realm 数据库存储的模型对象, 你要存储的数据都是继承自这个类的. 所以我们新建 Realm Model Object 文件时, 就会自动帮我们建立一个.h 和.m 文件
这个模型文件的作用还是相当大的, 先按下不表
做通讯录当然离不开 tableView, 如果说 CoreData 是和 NSFetchedResultsController互相配合, 那么 Realm 就是用到了 RLMResults 这个关键类
tableView 的数据源就是这么个东东
ViewController.m
// -------- 初始化数据源 --------
- (RLMResults<YFPerson *> *)resultsArray
{
if (!_resultsArray) {
/* 按照年龄来排序 */
_resultsArray = [[YFPerson allObjects]sortedResultsUsingProperty:@"age" ascending:YES];
}
return _resultsArray;
}
初始化数据源数组的时候还可以设置按照什么排序, 在这里, 我就按照年龄来排序
还有一个关键类就是RLMNotificationToken,通知令牌就是当数据库里的元素一发生变化, 就调用 block 里的代码,也非常的方便好用
- (RLMNotificationToken *)notificationToken
{
__weak typeof(self)weakSelf = self;
if (!_notificationToken) {
_notificationToken = [self.resultsArray addNotificationBlock:^(RLMResults<YFPerson *> * _Nullable results, RLMCollectionChange * _Nullable change, NSError * _Nullable error) {
if (error) {
NSLog(@"打开 realm 数据库失败,%@",error);
return;
}
/* 如果数据库的变化为空, 则仅仅刷新 tableView */
if (!change) {
[weakSelf.tableView reloadData];
}
/* 如果变化不为空,则更新 tableView的数据源, 并刷新 tableView */
/* tableView开始更新 */
[weakSelf.tableView beginUpdates];
/* tableView 删除数据 */
[weakSelf.tableView deleteRowsAtIndexPaths:[change deletionsInSection:0] withRowAnimation:UITableViewRowAnimationTop];// 因为只有第0组,所以所有的更新都在第0组
/* tableView 添加数据 */
[weakSelf.tableView insertRowsAtIndexPaths:[change insertionsInSection:0] withRowAnimation:UITableViewRowAnimationTop];
/* tableView 刷新数据 */
[weakSelf.tableView reloadRowsAtIndexPaths:[change modificationsInSection:0] withRowAnimation:UITableViewRowAnimationTop];
/* tableView 结束更新 */
[weakSelf.tableView endUpdates];
}];
}
/* 在这里打印一下沙盒的地址, 然后可以看到待会儿可以看到可视化的数据库 */
NSLog(@"%@",NSHomeDirectory());
return _notificationToken;
}
我们在 block 回调里面插入数据,删除数据,刷新 tableView, 做这样一些操作. 当数据库数据一发生变化, 就会做相应的操作, 并刷新 tableView
在上面这个方法, 打印下沙盒地址, 等下用的着
- 还有一个关键类, 就是操作数据库啦, 数据库无外乎四个字: 增,删,改,查
今天先讲一下增和删吧, 做了一个增加单个联系人,和批量增加联系人
1.增加单个联系人
RLMRealm 这个单例对象就是创建实例对象并存储到 Realm 数据库中
- (void)addUniquePerson
{
/* 这个类是专门开始创建数据库的 */
/* 开始写入业务 */
[[RLMRealm defaultRealm]beginWriteTransaction];
/* 这个方法是创造一个Realm实例对象,并存储到 Realm 数据库中 */
[YFPerson createInRealm:[RLMRealm defaultRealm] withValue:@[[self randomName],@([self randomAge])]];
/* 提交写入业务 */
[[RLMRealm defaultRealm]commitWriteTransaction];
}
很有必要说一下[YFPerson createInRealm:[RLMRealm defaultRealm] withValue:@[[self randomName],@([self randomAge])]];
这个方法, 这个方法是基于 KVC 的, 我们在设置 value 的时候可以传入NSJSONSerialization解析出来的数组和字典, 当传入数组的时候, 所有属性都必须填写, 并且要按这个模型对象定义属性时的顺序,否则就会报错
2.批量增加联系人
由于是耗时操作, 我们必须开启子线程
/* 添加多个数据 */
- (void)addManyPersons
{
/* 添加多个数据是耗时操作, 我们重新开启一个线程来操作 */
dispatch_async(dispatch_get_global_queue(0, 0), ^{
for (NSUInteger i = 0; i < 5; i++) {
/* 循环内部的逻辑就跟添加单个数据一样了 */
[[RLMRealm defaultRealm]beginWriteTransaction];
[YFPerson createInRealm:[RLMRealm defaultRealm] withValue:@[[self randomName],@([self randomAge])]];
[[RLMRealm defaultRealm]commitWriteTransaction];
}
});
}
只要增加和批量增加的方法被触发, 就会立马刷新到 tableView 上,并且顺序是按照年龄的升序来排列的, 这是才初始化数据源数组的时候设置好的
- 在侧滑删除中, 我们做一个删除数据的功能, 其实跟添加数据差不多的
// -------- 侧滑打开的方法 --------
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
/* 删除数据,其实方法和添加数据是差不多的 */
if (editingStyle == UITableViewCellEditingStyleDelete) {
[[RLMRealm defaultRealm]beginWriteTransaction];
[[RLMRealm defaultRealm]deleteObject:self.resultsArray[indexPath.row]];
[[RLMRealm defaultRealm]commitWriteTransaction];
}
}
整个效果做出来其实是这样的
效果图
那我们要看数据库在什么位置怎么办呢?
-
首先装一个
Realm 浏览器 -
在 APP Store 里下载
-
然后将之前打印出的沙盒地址来一个"前往"
-
数据库存储在 Documents 文件夹中
数据库地址 -
用Realm 浏览器打开后是这个样子滴, 你存储的对象都在里面
Realm 数据库
本文源码链接地址
Realm 数据库也是很博大精深的,大家一起探讨,感谢支持!
网友评论
数据库一般支持事务操作,不需要手动for循环添加
查阅api:[_relam addOrUpdateObjectsFromArray:@[id...]];
[_relam beginWriteTransaction];
//以下两种方法取其一
[_relam addOrUpdateObjectsFromArray:modelArr];//设置过主键的
//[_relam addObjects:modelArr]
//关闭事务
[_relam commitWriteTransaction];