Realm入門指北

簡介

接觸Realm已經(jīng)有一段時(shí)間了,但是一直忙著項(xiàng)目,一直沒有時(shí)間做一下筆記。趁著項(xiàng)目閑著之際,我開始著手記錄我自己使用Realm過程遇到的坑。Realm是一個(gè)跨平臺(tái)的數(shù)據(jù)庫,就拿iOS來說,數(shù)據(jù)庫常用的幾種無非是Sqlite、FMDB、CoreData這幾種,每一種數(shù)據(jù)庫都在某些方面有著特別的優(yōu)勢(shì)。對(duì)于coreData,在每次使用的時(shí)候都要?jiǎng)?chuàng)建一大堆的代碼,個(gè)人是累覺不愛。而對(duì)于Sqlite是基于C語言的,用起來也是相對(duì)麻煩,F(xiàn)MDB是基于Sqlite的封裝,用起來還相對(duì)友好一點(diǎn),但是還是要寫一大堆的sql語句,但是無可否認(rèn)的是,在API上FMDB還是蠻簡單上手的。但是今天重點(diǎn)介紹的是Realm.

Realm是由Y Combinator孵化的創(chuàng)業(yè)團(tuán)隊(duì)開源出來的一款可以用于iOS(同樣適用于Swift&Objective-C)和Android的跨平臺(tái)移動(dòng)數(shù)據(jù)庫。目前最新版是Realm 2.0.2,支持的平臺(tái)包括Java,Objective-C,Swift,React Native,Xamarin。

安裝方法主要有四種(在這就不做說明)
1.Dynamic Framework(動(dòng)態(tài)庫)
2.CocoaPod
3.Carthage(僅支持iOS8以上)
4.Static Framework

Realm 中的相關(guān)術(shù)語

為了能更好的理解Realm的使用,先介紹一下涉及到的相關(guān)術(shù)語。

RLMRealm:Realm是框架的核心所在,是我們構(gòu)建數(shù)據(jù)庫的訪問點(diǎn),就如同Core Data的管理對(duì)象上下文(managed object context)一樣。出于簡單起見,realm提供了一個(gè)默認(rèn)的defaultRealm( )的便利構(gòu)造器方法。

RLMObject:這是我們自定義的Realm數(shù)據(jù)模型。創(chuàng)建數(shù)據(jù)模型的行為對(duì)應(yīng)的就是數(shù)據(jù)庫的結(jié)構(gòu)。要?jiǎng)?chuàng)建一個(gè)數(shù)據(jù)模型,我們只需要繼承RLMObject,然后設(shè)計(jì)我們想要存儲(chǔ)的屬性即可。

關(guān)系(Relationships):通過簡單地在數(shù)據(jù)模型中聲明一個(gè)RLMObject類型的屬性,我們就可以創(chuàng)建一個(gè)“一對(duì)多”的對(duì)象關(guān)系。同樣地,我們還可以創(chuàng)建“多對(duì)一”和“多對(duì)多”的關(guān)系。

寫操作事務(wù)(Write Transactions):數(shù)據(jù)庫中的所有操作,比如創(chuàng)建、編輯,或者刪除對(duì)象,都必須在事務(wù)中完成?!笆聞?wù)”是指位于write閉包內(nèi)的代碼段。

查詢(Queries):要在數(shù)據(jù)庫中檢索信息,我們需要用到“檢索”操作。檢索最簡單的形式是對(duì)Realm( )數(shù)據(jù)庫發(fā)送查詢消息。如果需要檢索更復(fù)雜的數(shù)據(jù),那么還可以使用斷言(predicates)、復(fù)合查詢以及結(jié)果排序等等操作。

RLMResults:這個(gè)類是執(zhí)行任何查詢請(qǐng)求后所返回的類,其中包含了一系列的RLMObject對(duì)象。RLMResults和NSArray類似,我們可以用下標(biāo)語法來對(duì)其進(jìn)行訪問,并且還可以決定它們之間的關(guān)系。不僅如此,它還擁有許多更強(qiáng)大的功能,包括排序、查找等等操作。

Realm 的基本使用

1.創(chuàng)建數(shù)據(jù)庫
  • 1.使用系統(tǒng)默認(rèn)的數(shù)據(jù)庫
  • 2.自定義數(shù)據(jù)庫(代碼實(shí)現(xiàn)的是自定義的數(shù)據(jù)庫)

Object-C

RLMRealm *realm = [RLMRealm defaultRealm];
 - (BOOL) initRealm {
    RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
    config.fileURL = [[[config.fileURL URLByDeletingLastPathComponent]
                       URLByAppendingPathComponent:[NSString stringWithFormat:@"Message%lu",(unsigned long)self.messageType]]
                      URLByAppendingPathExtension:@"realm"];
    debugLog(@"Realm file path: %@", config.fileURL);
    NSError *error;
    _realm = [RLMRealm realmWithConfiguration:config error:&error];
    if (nil != error) {
        NSLog(@"Create Realm Error");
        return NO;
    }
    debugLog(@"create realm success");
    return YES;
}

Swift

    // MARK: - 初始化Rleam數(shù)據(jù)庫
    func createDataBase() {
        var config = Realm.Configuration()
        config.fileURL = config.fileURL?.deletingLastPathComponent().appendingPathComponent("HJQ").appendingPathExtension("Realm")
        var realm: Realm?
        do {
           realm =  try Realm.init(configuration: config)
        } catch  {
            debugLog(error)
        }
        debugLog(realm)
    }
2.建表

Object-C

#import <Foundation/Foundation.h>
#import <Realm/Realm.h>

@interface UserMessageList : RLMObject

@property NSString *title;
@property NSInteger linkType;
@property NSInteger messageId;
@property BOOL readStatus;
@property NSString *content;
@property long long createTime;
@property NSString *picUrl;

@end
RLM_ARRAY_TYPE(UserMessageList);

@interface GFBUserMessageMD : RLMObject

@property NSString *username;
@property RLMArray<UserMessageList> *userMessageList;

@end
RLM_ARRAY_TYPE(GFBUserMessageMD);

注意,RLMObject 官方建議不要加上 Objective-C的property attributes(如nonatomic, atomic, strong, copy, weak 等等)假如設(shè)置了,這些attributes會(huì)一直生效直到RLMObject被寫入realm數(shù)據(jù)庫。

RLM_ARRAY_TYPE宏創(chuàng)建了一個(gè)協(xié)議,從而允許 RLMArray<GFBUserMessageMD>語法的使用。如果該宏沒有放置在模型接口的底部的話,您或許需要提前聲明該模型類。

關(guān)于RLMObject的的關(guān)系

1.對(duì)一(To-One)關(guān)系

對(duì)于多對(duì)一(many-to-one)或者一對(duì)一(one-to-one)關(guān)系來說,只需要聲明一個(gè)RLMObject子類類型的屬性即可

2.對(duì)多(To-Many)關(guān)系(重點(diǎn)介紹)
通過 RLMArray類型的屬性您可以定義一個(gè)對(duì)多關(guān)系。如上面代碼例子,@property RLMArray<UserMessageList> *userMessageList;

3.反向關(guān)系(Inverse Relationship)

#import "GFBUserMessageMD.h"

@implementation GFBUserMessageMD
// 為了保證表的唯一性,設(shè)置主鍵
+ (NSString *)primaryKey {
    return @"username";
}

@end
@implementation UserMessageList

@end

Swift

import UIKit
import RealmSwift
>
class UserMessageMD: Object {
    dynamic var title: String?
    dynamic var messageID: String!
}
>
class UserMD: Object {
    dynamic var userID: String!
    dynamic var name: String!
    >
    // List 是個(gè)泛型
    var userMessages = List<UserMessageMD>()
    >
    // MARK: - 設(shè)置主鍵
    override static func primaryKey() -> String? {
        return "userID"
    }
}
3.數(shù)據(jù)的插入

Object-C

- (void) insertOrCreateData:(GFBSysMessageListMD *)md {
    GFBUserMessageMD *userMD;
    NSString *userId = [QFUserInfo shareInfo].username;
    if (! userId) {
        return;
    }
    // 查詢當(dāng)前是否有這個(gè)表
    if ([GFBUserMessageMD objectInRealm:_realm forPrimaryKey:userId]) {
        userMD = [GFBUserMessageMD objectInRealm:_realm forPrimaryKey:userId];
    }else {
        userMD = [GFBUserMessageMD new];
        userMD.username = userId;
    }
    [_realm transactionWithBlock:^{
        for (int i = 0; i < md.data.content.count; i++) {
            SysMessageListContent *model = md.data.content[i];
            UserMessageList *userMessageMD;
            NSPredicate *pred = [NSPredicate predicateWithFormat:@"messageId = %li",model.id];
            if([userMD.userMessageList indexOfObjectWithPredicate:pred] != NSNotFound) { // 如果該數(shù)據(jù)已經(jīng)存在則無需重新插入
                NSUInteger index = [userMD.userMessageList indexOfObjectWithPredicate:pred];
                userMessageMD = userMD.userMessageList[index];
                debugLog(@"我是查詢的結(jié)果%lu",index);
            }else{
                // 插入新的數(shù)據(jù)
                userMessageMD = [UserMessageList new];
                userMessageMD.title = model.title;
                userMessageMD.messageId = model.id;
                userMessageMD.content = model.content;
                userMessageMD.createTime = model.createTime;
                userMessageMD.readStatus = NO;
                userMessageMD.linkType = model.linkType;
                userMessageMD.picUrl = model.picUrl;
                [userMD.userMessageList addObject:userMessageMD];
            }
        }
        [GFBUserMessageMD createOrUpdateInRealm:_realm withValue:userMD];
    }];
}

Swift

// MARK: - 建表插入數(shù)據(jù)
    func insertData() {
        let realm = try! Realm()
        // 通過主鍵查找到對(duì)應(yīng)的數(shù)據(jù)
        var userMD = realm.object(ofType: UserMD.self,forPrimaryKey: "")
        if userMD == nil {
            userMD = UserMD()
        }
        let messageID = "10000"
        try! realm.write {
            var userMessageMD: UserMessageMD? = nil
            let pred = NSPredicate(format: "messageID = \(messageID) ")
            let resultIndex = userMD!.userMessages.index(matching: pred)
            if resultIndex != NSNotFound { // 已經(jīng)存在
                userMessageMD = userMD!.userMessages[resultIndex!]
            }else {
                userMessageMD = UserMessageMD()
                // 不存在則繼續(xù)追加
                userMD?.userMessages.append(userMessageMD!)
            }
            realm.add(userMD!, update: true)
        }
    }
4.數(shù)據(jù)的更新
- (void) updateReadStatus:(NSInteger) index {
    GFBUserMessageMD *userMD;
    NSString *userId = [QFUserInfo shareInfo].username;
    if (! userId) {
        return;
    }
    // 查詢當(dāng)前是否有這個(gè)表
    if ([GFBUserMessageMD objectInRealm:_realm forPrimaryKey:userId]) {
        userMD = [GFBUserMessageMD objectInRealm:_realm forPrimaryKey:userId];
    }
    if (userMD) {
        [_realm transactionWithBlock:^{
            UserMessageList *userMessageMD = userMD.userMessageList[index];
            userMessageMD.readStatus = YES;
            [GFBUserMessageMD createOrUpdateInRealm:_realm withValue:userMD];
        }];
    }
}
5.數(shù)據(jù)的查詢

Object-C

// 查找所有的數(shù)據(jù)
- (void) queryAllData {
    GFBUserMessageMD *userMD;
    NSString *userId = [QFUserInfo shareInfo].username;
    if (! userId) {
        return;
    }
    // 查詢當(dāng)前是否有這個(gè)表
    if ([GFBUserMessageMD objectInRealm:_realm forPrimaryKey:userId]) {
        userMD = [GFBUserMessageMD objectInRealm:_realm forPrimaryKey:userId];
    }
    if (userMD) {
        debugLog(@"當(dāng)前存在的數(shù)據(jù)%@",userMD.userMessageList);
    }
}

Swift

    // MARK: - 查詢數(shù)據(jù)
    func queriesDatas() {
        let realm = try! Realm()
        // 通過主鍵查找到對(duì)應(yīng)的數(shù)據(jù)
        let userMD = realm.object(ofType: UserMD.self,forPrimaryKey: "")
        debugLog(userMD)
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容