持久化方案-Reaml數(shù)據(jù)庫簡介

一、Realm官網(wǎng)地址:https://realm.io/cn/
二、Realm框架介紹:
    realm是一個跨平臺移動數(shù)據(jù)庫引擎,支持iOS、OS X(Objective-C和Swift)以及Android;
    核心數(shù)據(jù)引擎C++打造,并不是建立在SQLite之上的ORM, 是擁有獨立的數(shù)據(jù)庫存儲引擎;
    比sqlite, coredata效率更快、簡單易用。
三、Realm輔助工具:
    1、RealmBrowser:可視化訪問Realm數(shù)據(jù)庫(AppStore中可下載)
    2、Xcode插件:reaml-cocoa可以快速創(chuàng)建Realm可存儲模型對象
      (https://github.com/realm/realm-cocoa)
四、Realm支持的數(shù)據(jù)類型:
    BOOL, bool, int, NSInteger, long, long long, float, double, NSString, NSDate, NSData, and NSNumber
    注意:不支持集合類型 
    解決方案:序列化成NSData進行存儲 或 轉(zhuǎn)換成RLMArray<RLMObject>進行存儲(麻煩)
五、Realm數(shù)據(jù)庫:
    1. 用戶機制:不同的用戶, 使用不同的數(shù)據(jù)庫
      + (void)setDefaultRealmForUser:(NSString *)username {
            RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
            // 使用默認的目錄,但是使用用戶名來替換默認的文件名
            config.fileURL = [[[config.fileURL URLByDeletingLastPathComponent] URLByAppendingPathComponent:username] URLByAppendingPathExtension:@"realm"];  
            // 將這個配置應(yīng)用到默認的 Realm 數(shù)據(jù)庫當中
            [RLMRealmConfiguration setDefaultConfiguration:config];
       }

    2. 只讀方式打開數(shù)據(jù)庫:config.readOnly = YES;

    3. 數(shù)據(jù)庫文件刪除:需要刪除數(shù)據(jù)庫文件以及輔助文件(官方要求)
       NSFileManager *manager = [NSFileManager defaultManager];
       RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
       NSArray<NSURL *> *realmFileURLs = @[config.fileURL, 
                                          [config.fileURL URLByAppendingPathExtension:@"lock"], 
                                          [config.fileURL URLByAppendingPathExtension:@"log_a"],
                                          [config.fileURL URLByAppendingPathExtension:@"log_b"],
                                          [config.fileURL URLByAppendingPathExtension:@"note"]
                                          ];
       for (NSURL *URL in realmFileURLs){  
            NSError *error = nil; 
           [manager removeItemAtURL:URL error:&error];
           if(error){//處理錯誤}
       }
六、Realm增刪改查:首先創(chuàng)建數(shù)據(jù)模型, 必須繼承自RLMObject
    6.1 創(chuàng)建對象的方式:1. 普通創(chuàng)建
                     2. 通過父類RLMObject中的方法快速創(chuàng)建:initWithValue(數(shù)組或字典)
                        請注意:跟屬性順序需保持一致;
                        所有的必需屬性都必須在對象添加到Realm前被賦值;
                        由于Realm在自己的引擎內(nèi)部有很好的語義解釋系統(tǒng),
                        所以 Objective?C 的許多屬性特性將被忽略,
                        如nonatomic, atomic, strong, copy 和 weak 等,
                        因此為了避免誤解,官方推薦在編寫數(shù)據(jù)模型的時候不要使用任何的屬性特性。
    6.2 簡單的數(shù)據(jù)操作:
                     1. 保存指定模型:
                        獲取RLMRealm對象:RLMRealm *realm = [RLMRealm defaultRealm];
                        方式1:開啟寫入事務(wù):[realm beginWriteTransaction];
                              添加模型對象:[realm addObject:stu];
                              提交寫入事務(wù):[realm commitWriteTransaction];

                        方式2:[realm transactionWithBlock:^{
                                   [realm addObject:stu];
                              }];

                        方式3:[Stu createInRealm:realm withValue:@{@"stu_id": @22, @"name": @"馬冬梅2", @"age": @666}];

                     2. 更新指定模型
                        方式1:在事務(wù)中直接更新對象
                              [realm beginWriteTransaction];
                              stu.name = @"土豆";
                              [realm commitWriteTransaction];

                        方式2:根據(jù)主鍵進行更新
                              1. 要求操作的模型, 必須實現(xiàn)方法
                                 + (NSString *)primaryKey 返回主鍵
                              2. 在事務(wù)中調(diào)用方法:[realm addOrUpdateObject:stu2];

                        方式3:根據(jù)主鍵進行更新
                              1. 要求操作的模型, 必須實現(xiàn)方法
                                 + (NSString *)primaryKey 返回主鍵
                              2. 在事務(wù)中調(diào)用方法:
                                 [Stu createOrUpdateInRealm:realm withValue:@{@"stu_id": @22, @"name": @"馬冬梅2", @"age": @666}];

                      3. 使用RLMRealm對象, 在事務(wù)中刪除數(shù)據(jù)
                        方式1:刪除指定的對象,
                              注意: 必須是從realm數(shù)據(jù)庫中獲取的模型對象, 而不是自己創(chuàng)建的
                              RLMObject *obj = [realm objectWithClassName:@"Stu" forPrimaryKey:@2];
                              [realm deleteObject:obj];
                     
                        方式2:刪除所有對象
                              [realm deleteAllObjects];

                     4. 使用RLMRealm對象, 查詢數(shù)據(jù)
                       注意事項:1. 所有的查詢(包括查詢和屬性訪問)在Realm中都是延遲加載的,
                               只有當屬性被訪問時,才能夠讀取相應(yīng)的數(shù)據(jù);
                               2. 查詢結(jié)果并不是數(shù)據(jù)的拷貝:
                               修改查詢結(jié)果(在寫入事務(wù)中)會直接修改硬盤上的數(shù)據(jù);
                               3. 一旦檢索執(zhí)行之后, RLMResults將隨時保持更新。

                       查詢所有:[Stu allObjects]

                       條件查詢:RLMResults<Stu *> *stus = [Stu objectsWhere:@"name = '馬冬梅'"];

                       排序查詢:[stus sortedResultsUsingProperty:@"name" ascending:YES];

                       鏈式查詢:在查詢結(jié)果的基礎(chǔ)上, 進行二次查詢
                               [stus objectsWhere:@"address beginswith '北京'"];

                       分頁查詢:查詢出來的結(jié)果對象是懶加載, 只有真正訪問時, 
                               才會加載相應(yīng)對象, 所以這里的分頁, 其實就是從所有集合中分頁獲取即可
                               RLMResults<Dog *> *dogs = [Dog allObjects];
                               for (NSInteger i = 0; i < 5; i++) {
                                    Dog *dog = dogs[i];
                                    // …
                               }
七、Realm關(guān)系:
    7.1 對一關(guān)系:當一個對象持有另外一個對象時, 比如人有一個寵物??
    7.2 對多關(guān)系:1. 在Dog中, 遵循指定協(xié)議方法
                   RLM_ARRAY_TYPE(Dog):
                   RLM_ARRAY_TYPE 宏創(chuàng)建了一個協(xié)議,從而允許 RLMArray<Dog> 語法的使用
                2. 在Person中, 定義屬性:
                   @property (nonatomic, strong) RLMArray<Dog *><Dog> *dogs;
                   雖然可以給 RLMArray 屬性賦值為 nil,
                   但是這僅用于“清空”數(shù)組,而不是用以移除數(shù)組。
                   這意味著您總是可以向一個 RLMArray 屬性中添加對象,
                   即使其被置為了 nil。
                   Person屬性意義解釋:RLMArray: 屬性類型。
                                    <Object *>: 屬性的特別化(generic specialization),
                                                這可以阻止在編譯時使用錯誤對象類型的數(shù)組。
                                    <Object>: 此RLMArray遵守的協(xié)議,
                                                可以讓 Realm 知曉如何在運行時確定數(shù)據(jù)模型的結(jié)構(gòu)。
    7.3 反向關(guān)系:人擁有狗, 狗又有相應(yīng)的主人?
                1. Dog中定義屬性:@property (readonly) RLMLinkingObjects *master;
                2. 實現(xiàn)協(xié)議方法, 標明鏈接關(guān)系:
                   + (NSDictionary<NSString *,RLMPropertyDescriptor *> *)linkingObjectsProperties {
                         return @{
                                 @"master": [RLMPropertyDescriptor descriptorWithClass:NSClassFromString(@"Stu") propertyName:@"dogs"]
                                 };
                   }
八、可空屬性&默認值&忽略屬性:
    默認情況下, 屬性值可空, 如果強制要求某個屬性非空, 可以使用如下方法
    8.1 設(shè)置屬性不能為nil:+ (NSArray *)requiredProperties;
        特點:如果再次賦值為nil, 則會拋出異常錯誤
    8.2 設(shè)置屬性默認值:+ (NSDictionary *)defaultPropertyValues;
    8.3 設(shè)置可忽略屬性:+ (NSArray *)ignoredProperties;
    開發(fā)經(jīng)驗:可以借助忽略屬性&只讀屬性打造計算屬性, 完成集合以及UIImage對象的存儲與獲取
九、Realm數(shù)據(jù)庫通知:
    數(shù)據(jù)庫和結(jié)果集都可添加通知;Realm實例將會在每次寫入事務(wù)提交后,
                           給其他線程上的Realm實例發(fā)送通知;必須持有返回的token
    9.1 獲取Realm通知:
        self.token = [realm addNotificationBlock:^(NSString *notification, RLMRealm * realm) {
                        // 接收到更改通知, 需要做的事情
                      }];
    9.2 移除通知:[self.token stop];
十、Realm數(shù)據(jù)庫遷移:
    10.1 數(shù)據(jù)結(jié)構(gòu)的遷移:
         // 在 [AppDelegate didFinishLaunchingWithOptions:] 中進行配置
         RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
         // 設(shè)置新的架構(gòu)版本。
         // 這個版本號必須高于之前所用的版本號
         //(如果您之前從未設(shè)置過架構(gòu)版本,那么這個版本號設(shè)置為 0)
         config.schemaVersion = 1;
         // 設(shè)置閉包,這個閉包將會在打開低于上面所設(shè)置版本號的 Realm 數(shù)據(jù)庫的時候被自動調(diào)用
         config.migrationBlock = ^(RLMMigration *migration, uint64_t oldSchemaVersion) {
                // 目前我們還未進行數(shù)據(jù)遷移,因此 oldSchemaVersion == 0
                if (oldSchemaVersion < 1) {
                // 什么都不要做!
                // Realm 會自行檢測新增和需要移除的屬性,然后自動更新硬盤上的數(shù)據(jù)庫架構(gòu)
                }
         };
         // 告訴 Realm 為默認的 Realm 數(shù)據(jù)庫使用這個新的配置對象
         [RLMRealmConfiguration setDefaultConfiguration:config];
         // 現(xiàn)在我們已經(jīng)告訴了 Realm 如何處理架構(gòu)的變化,打開文件之后將會自動執(zhí)行遷移
         [RLMRealm defaultRealm];

    10.2 數(shù)據(jù)的遷移:
         // enumerateObjects:block: 方法遍歷了存儲在 Realm 文件中的每一個“Person”對象
         [migration enumerateObjects:Person.className block:^(RLMObject *oldObject, RLMObject *newObject) {
               // 將名字進行合并,存放在 fullName 域中
               newObject[@"fullName"] = [NSString stringWithFormat:@"%@ %@",
                                                  oldObject[@"firstName"],
                                                  oldObject[@"lastName"]];
         }];

     10.3 屬性重命名:
         [migration renamePropertyForClass:Person.className oldName:@"yearsSinceBirth" newName:@"age"];

     10.4 多版本增量式遷移:根據(jù)數(shù)據(jù)庫版本的不同,修改成最新版本(注意不要丟失數(shù)據(jù))
          // enumerateObjects:block: 遍歷了存儲在 Realm 文件中的每一個“Person”對象
          [migration enumerateObjects:Person.className block:^(RLMObject *oldObject, RLMObject *newObject) {
                  // 只有當 Realm 數(shù)據(jù)庫的架構(gòu)版本為 0 的時候,才添加 “fullName” 屬性
                  if (oldSchemaVersion < 1) {
                         newObject[@"fullName"] = [NSString stringWithFormat:@"%@ %@",
                                                            oldObject[@"firstName"],
                                                            oldObject[@"lastName"]];
                  }
          // 只有當 Realm 數(shù)據(jù)庫的架構(gòu)版本為 0 或者 1 的時候,才添加“email”屬性
          if (oldSchemaVersion < 2) {
                newObject[@"email"] = @"";
          }
          }];
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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