Realm -- oc版實(shí)踐(下)

前言

如果您對(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中完成习勤。

image.png
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ù)文章漩氨,謝謝大家指正。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末遗增,一起剝皮案震驚了整個(gè)濱河市叫惊,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌做修,老刑警劉巖霍狰,帶你破解...
    沈念sama閱讀 219,270評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件抡草,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡蔗坯,警方通過查閱死者的電腦和手機(jī)康震,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來宾濒,“玉大人腿短,你說我怎么就攤上這事』婷危” “怎么了橘忱?”我有些...
    開封第一講書人閱讀 165,630評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長卸奉。 經(jīng)常有香客問我钝诚,道長,這世上最難降的妖魔是什么榄棵? 我笑而不...
    開封第一講書人閱讀 58,906評(píng)論 1 295
  • 正文 為了忘掉前任凝颇,我火速辦了婚禮,結(jié)果婚禮上秉继,老公的妹妹穿的比我還像新娘祈噪。我一直安慰自己,他們只是感情好尚辑,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評(píng)論 6 392
  • 文/花漫 我一把揭開白布辑鲤。 她就那樣靜靜地躺著,像睡著了一般杠茬。 火紅的嫁衣襯著肌膚如雪月褥。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,718評(píng)論 1 305
  • 那天瓢喉,我揣著相機(jī)與錄音宁赤,去河邊找鬼。 笑死栓票,一個(gè)胖子當(dāng)著我的面吹牛决左,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播走贪,決...
    沈念sama閱讀 40,442評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼佛猛,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了坠狡?” 一聲冷哼從身側(cè)響起继找,我...
    開封第一講書人閱讀 39,345評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎逃沿,沒想到半個(gè)月后婴渡,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體幻锁,經(jīng)...
    沈念sama閱讀 45,802評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評(píng)論 3 337
  • 正文 我和宋清朗相戀三年边臼,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了哄尔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,117評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡硼瓣,死狀恐怖究飞,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情堂鲤,我是刑警寧澤,帶...
    沈念sama閱讀 35,810評(píng)論 5 346
  • 正文 年R本政府宣布媒峡,位于F島的核電站瘟栖,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏谅阿。R本人自食惡果不足惜半哟,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望签餐。 院中可真熱鬧寓涨,春花似錦、人聲如沸氯檐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽冠摄。三九已至糯崎,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間河泳,已是汗流浹背沃呢。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拆挥,地道東北人薄霜。 一個(gè)月前我還...
    沈念sama閱讀 48,377評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像纸兔,于是被迫代替她去往敵國和親惰瓜。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容