前言
如果您对Realm 基础还没有很了解的话,请阅读Realm -- oc版使用(上)
上篇中,我们已经讲了Realm 的数据模型,增删改查基础操作。
接下来,我们就来说说项目实践中“踩坑”。
数据模型必须继承RLMObject
与数据库操作相关的model当然要继承RLMObject,不过,我们可以新建model,专门用来接收服务端数据,利用MJExtension等方法,model转化成RLMmodel后进行存储,model的继承就与RLMObject没有关系了,虽然model可以继承任意类型,但是如果有多个RLMmodel存在,就要实现多个model,文件增加,维护起来不方便。(有利有弊)
下图是上述思想的扩展,所有的数据库基础操作都在BaseDBModel中完成。
image.pngRealm不支持集合类型
- 集合类型:NSArray,NSMutableArray,NSDictionary,NSMutableDictionary,NSSet,NSMutableSet等。
比如,服务端返回数据中存在字典,可以把字典中key提出来,新建一个RLMObject�模型,与之前的模型创建关系,或者只能把字典转换成NSString或者NSData类型进行存储。
Realm的加密方案
在创建 Realm 数据库时采用64位的密钥对数据库文件进行 AES-256+SHA2 加密,通过设置encryptionKey 进行加密。
RLMRealmConfiguration *configuration = [RLMRealmConfiguration defaultConfiguration];
NSString *path = [self db_currentRealmPath];
if (path) {
configuration.fileURL = [NSURL fileURLWithPath:path];
}
#ifdef DEBUG
configuration.encryptionKey = nil;
#else
configuration.encryptionKey = [self db_getKey];
#endif
NSError *e = nil;
realm = [RLMRealm realmWithConfiguration:configuration error:&e];
以下是Realm的UI更新通知,项目中还未使用
Realm 通知
Realm 的写操作事务被提交之后,无论这个事务发生在何种线程或者何种进程之中,这个通知处理闭包都将会被触发:
// 获取 Realm 通知
token = [realm addNotificationBlock:^(NSString *notification, RLMRealm * realm) {
[myViewController updateUI];
}];// 随后
[token stop];
集合通知
包括:已插入对象、已删除对象,或者已修改对象的索引,这三种操作的通知。
集合通知是异步触发的,首先它会在初始结果出现的时候触发,随后当某个写入事务改变了集合中的所有或者某个对象的时候,通知都会再次触发。
// 观察 RLMResults 通知
__weak typeof(self) weakSelf = self;
self.notificationToken = [[Person objectsWhere:@"age > 5"] addNotificationBlock:^(RLMResults<Person *> *results, RLMCollectionChange *changes, NSError *error) {
if (error) {
NSLog(@"Failed to open Realm on background worker: %@", error);
return;
}
UITableView *tableView = weakSelf.tableView;
// 对于变化信息来说,检索的初次运行将会传递 nil
if (!changes) {
[tableView reloadData];
return;
}
// 检索结果被改变,因此将它们应用到 UITableView 当中
[tableView beginUpdates];
[tableView deleteRowsAtIndexPaths:[changes deletionsInSection:0]
withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView insertRowsAtIndexPaths:[changes insertionsInSection:0]
withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView reloadRowsAtIndexPaths:[changes modificationsInSection:0]
withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView endUpdates];
}];
}
对象通知
Realm 支持对象级别的通知。
在此对象被删除时、被修改时获取相应的通知。
RLMStepCounter *counter = [[RLMStepCounter alloc] init];
counter.steps = 0;
RLMRealm *realm = [RLMRealm defaultRealm];
[realm beginWriteTransaction];
[realm addObject:counter];
[realm commitWriteTransaction];
__block RLMNotificationToken *token = [counter addNotificationBlock:^(BOOL deleted,
NSArray<RLMPropertyChange *> *changes,
NSError *error) {
if (deleted) {
NSLog(@"The object was deleted.");
} else if (error) {
NSLog(@"An error occurred: %@", error);
} else {
[token stop];
token = nil;
}
}];
UI更新通知
- [RLMCollection addNotificationBlock:]
// Observe RLMResults Notifications
__weak typeof(self) weakSelf = self;
//self.notificationToken -- >RLMNotificationToken
//self.collection -->id<RLMCollection> collection 对应返回的RLMResults
self.notificationToken = [self.collection addNotificationBlock:^(RLMResults<Item *> *results, RLMCollectionChange *changes, NSError *error) {
if (error) {
NSLog(@"Failed to open Realm on background worker: %@", error);
return;
}
UITableView *tableView = weakSelf.tableView;
// Initial run of the query will pass nil for the change information
if (!changes) {
[tableView reloadData];
return;
}
// Query results have changed, so apply them to the UITableView
[tableView beginUpdates];
[tableView deleteRowsAtIndexPaths:[changes deletionsInSection:0]
withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView insertRowsAtIndexPaths:[changes insertionsInSection:0]
withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView reloadRowsAtIndexPaths:[changes modificationsInSection:0]
withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView endUpdates];
}];
- (void)insertItem {
// Perform an interface-driven write on the main thread:
[self.collection.realm beginWriteTransaction];
[self.collection insertObject:[Item new] atIndex:0];
// And mirror it instantly in the UI
[tableView insertRowsAtIndexPaths:[NSIndexPath indexPathForRow:0 inSection:0]
withRowAnimation:UITableViewRowAnimationAutomatic];
// Making sure the change notification doesn't apply the change a second time
[self.collection.realm commitWriteTransactionWithoutNotifying:@[token]];
}
通过本次项目中使用realm开始学习,发现更多基础知识可以先从官方文档看起,然后循循渐进,通过阅读github相关资料的源码,更深入学习realm。
强烈推荐
Realm数据库 从入门到“放弃”
该文章还较详细的介绍了从其他数据库迁移到Realm中的问题,还有其他realm的优缺点,很赞。
有意见或建议请评论留言,新人写技术文章,谢谢大家指正。
网友评论