前言
如果您對(duì)Realm 基礎(chǔ)還沒有很了解的話王财,請(qǐng)閱讀Realm -- oc版使用(上)
上篇中,我們已經(jīng)講了Realm 的數(shù)據(jù)模型底扳,增刪改查基礎(chǔ)操作酿雪。
接下來遏暴,我們就來說說項(xiàng)目實(shí)踐中“踩坑”。
數(shù)據(jù)模型必須繼承RLMObject
與數(shù)據(jù)庫操作相關(guān)的model當(dāng)然要繼承RLMObject指黎,不過朋凉,我們可以新建model,專門用來接收服務(wù)端數(shù)據(jù)醋安,利用MJExtension等方法杂彭,model轉(zhuǎn)化成RLMmodel后進(jìn)行存儲(chǔ),model的繼承就與RLMObject沒有關(guān)系了吓揪,雖然model可以繼承任意類型亲怠,但是如果有多個(gè)RLMmodel存在,就要實(shí)現(xiàn)多個(gè)model柠辞,文件增加团秽,維護(hù)起來不方便。(有利有弊)
下圖是上述思想的擴(kuò)展叭首,所有的數(shù)據(jù)庫基礎(chǔ)操作都在BaseDBModel中完成习勤。
Realm不支持集合類型
- 集合類型:NSArray,NSMutableArray焙格,NSDictionary图毕,NSMutableDictionary,NSSet眷唉,NSMutableSet等吴旋。
比如损肛,服務(wù)端返回?cái)?shù)據(jù)中存在字典,可以把字典中key提出來荣瑟,新建一個(gè)RLMObject?模型,與之前的模型創(chuàng)建關(guān)系摩泪,或者只能把字典轉(zhuǎn)換成NSString或者NSData類型進(jìn)行存儲(chǔ)笆焰。
Realm的加密方案
在創(chuàng)建 Realm 數(shù)據(jù)庫時(shí)采用64位的密鑰對(duì)數(shù)據(jù)庫文件進(jìn)行 AES-256+SHA2 加密,通過設(shè)置encryptionKey 進(jìn)行加密见坑。
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更新通知嚷掠,項(xiàng)目中還未使用
Realm 通知
Realm 的寫操作事務(wù)被提交之后,無論這個(gè)事務(wù)發(fā)生在何種線程或者何種進(jìn)程之中荞驴,這個(gè)通知處理閉包都將會(huì)被觸發(fā):
// 獲取 Realm 通知
token = [realm addNotificationBlock:^(NSString *notification, RLMRealm * realm) {
[myViewController updateUI];
}];// 隨后
[token stop];
集合通知
包括:已插入對(duì)象不皆、已刪除對(duì)象,或者已修改對(duì)象的索引,這三種操作的通知熊楼。
集合通知是異步觸發(fā)的霹娄,首先它會(huì)在初始結(jié)果出現(xiàn)的時(shí)候觸發(fā),隨后當(dāng)某個(gè)寫入事務(wù)改變了集合中的所有或者某個(gè)對(duì)象的時(shí)候鲫骗,通知都會(huì)再次觸發(fā)犬耻。
// 觀察 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;
// 對(duì)于變化信息來說,檢索的初次運(yùn)行將會(huì)傳遞 nil
if (!changes) {
[tableView reloadData];
return;
}
// 檢索結(jié)果被改變执泰,因此將它們應(yīng)用到 UITableView 當(dāng)中
[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];
}];
}
對(duì)象通知
Realm 支持對(duì)象級(jí)別的通知枕磁。
在此對(duì)象被刪除時(shí)、被修改時(shí)獲取相應(yīng)的通知术吝。
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 對(duì)應(yīng)返回的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]];
}
通過本次項(xiàng)目中使用realm開始學(xué)習(xí)计济,發(fā)現(xiàn)更多基礎(chǔ)知識(shí)可以先從官方文檔看起,然后循循漸進(jìn)排苍,通過閱讀github相關(guān)資料的源碼沦寂,更深入學(xué)習(xí)realm。
強(qiáng)烈推薦
Realm數(shù)據(jù)庫 從入門到“放棄”
該文章還較詳細(xì)的介紹了從其他數(shù)據(jù)庫遷移到Realm中的問題纪岁,還有其他realm的優(yōu)缺點(diǎn)凑队,很贊。
有意見或建議請(qǐng)?jiān)u論留言幔翰,新人寫技術(shù)文章漩氨,謝謝大家指正。