iOS中Realm資料庫的基本用法

来源:https://www.cnblogs.com/jukaiit/archive/2018/07/17/9321843.html
-Advertisement-
Play Games

原文 http://git.devzeng.com/blog/simple-usage-of-realm-in-ios.html 主題 Realm iOS開發 Realm是由 Y Combinator 公司孵化的一款支持運行在手機、平板和可穿戴設備上的嵌入式資料庫(旨在取代CoreData和Sqli ...


  原文  http://git.devzeng.com/blog/simple-usage-of-realm-in-ios.html 主題 Realm iOS開發

Realm是由 Y Combinator 公司孵化的一款支持運行在手機、平板和可穿戴設備上的嵌入式資料庫(旨在取代CoreData和Sqlite)。Realm並不是對Core Data的簡單封裝,相反地,Realm並不是基於Core Data,也不是基於SQLite所構建的。它擁有自己的資料庫存儲引擎,可以高效且快速地完成資料庫的構建操作。 

Realm可以輕鬆地移植到項目當中,並且絕大部分常用的功能(比如說插入、查詢等等)都可以用一行簡單的代碼輕鬆完成!目前支持Objective-C、Swift和Java三種語言,也就是說能在iOS、Android和Mac上面跨平臺使用。

綜上,Realm主要有以下幾個優點:

  • Easy to Use(簡單易用):Core Data和SQLite冗餘、繁雜的知識和代碼足以嚇退絕大多數剛入門的開發者,而換用Realm,則可以極大地減少學習代價和學習時間,讓應用及早用上數據存儲功能。

  • Cross-Platform(跨平臺):現在絕大多數的應用開發並不僅僅只在iOS平臺上進行開發,還要兼顧到Android平臺的開發。為兩個平臺設計不同的資料庫是愚蠢的,而使用Realm資料庫,iOS和Android無需考慮內部數據的架構,調用Realm提供的API就可以完成數據的交換,實現“一個資料庫,兩個平臺無縫銜接”。

  • Fast(高效):Realm相比使用CoreData和原生的SQLite來說速度更快更加高效,而且代碼量更少。

快速集成Realm

1、下載最新的 Realm 更新包,解壓zip文件 

2、將 ios/static 目錄下麵的 Realm.framework 文件拖到項目裡面(確保Copy items if needed選中) 

3、在 target -> Build Phases -> Link Binary with Libraries 中添加 libc++.dylib

說明:

(1)對於使用Swift的童鞋,請講Swift/RLMSupport.swift文件拖到項目中(確保Copy items if needed選中)

(2)推薦使用Cocoapods進行安裝,在Podfile中添加 pod 'Realm' 即可 

(3)也可以自行到Github上面下載代碼進行編譯,此處不作過多的介紹

運行環境:

(1)支持 >= iOS7.0, >= OS X 10.9, 及WatchKit

(2)推薦使用Xcode 5以上的IDE,支持Swift

輔助工具和插件的安裝

 

1、Realm Browser

Realm官方非常貼心的向開發者提供了一個用於查看喝編輯Realm數據的工具 Realm Browser . 

在上面下載的更新包的 browser/ 下麵有個Realm Browser拖到Application文件夾或者是直接打開都行。另外可以使用菜單的 tool -> generate demo datebase ,生成測試數據用於測試Realm資料庫的使用 

2、Xcode Plugin(Xcode8之後好像蘋果大大不再支持Xcode插件,如果硬是要使用插件,還是有辦法的,請自行谷歌)

在Realm中使用到最多的是Realm Model(繼承自RLMObject的類,後面有介紹)。官方提供了一個Xcode的插件讓我們在創建模型變得非常輕鬆

安裝使用:

(1)最簡單的安裝方式是通過Alcatraz,搜索 RealmPlugin 直接安裝 

(2)或者是打開zip文件夾下麵的 plugin/RealmPlguin.xcodeproj ,build一下就安裝好了 

安裝完後重啟Xcode生效,在創建model的時候選擇New File(或⌘N),選擇Realm按照要求輸入model的名字就OK啦。

Realm的使用

1、構建資料庫

Realm提供了三種方式創建資料庫,一種是存儲在預設路徑下的資料庫,一種是我們可以自己指定資料庫文件的存儲路徑和只讀屬性,另外還可以使用記憶體資料庫。

(1)預設Realm資料庫

RLMRealm *realm = [RLMRealm defaultRealm];

可以通過: [RLMRealm defaultRealmPath] 查看預設存儲的路徑。 

(2)自定義Realm資料庫

NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *dbPath = [docPath stringByAppendingPathComponent:@"db/db.realm"];
RLMRealm *realm = [RLMRealm realmWithPath:dbPath];

或者是

NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *dbPath = [docPath stringByAppendingPathComponent:@"db/db.realm"];
RLMRealm *realm = [RLMRealm realmWithPath:dbPath readOnly:YES error:nil];

其中readOnly表示創建的資料庫是只讀資料庫。

(3)記憶體資料庫

正常的Realm資料庫是存儲在硬碟上的, 但你也可以通過使用 + (instancetype)inMemoryRealmWithIdentifier:(NSString *)identifier; 來創建一個記憶體資料庫。 

RLMRealm *realm = [RLMRealm inMemoryRealmWithIdentifier:@"test"];

註意:記憶體資料庫在每次程式退出時不會保存數據。如果某個記憶體Realm實例沒有被引用,所有的數據在實例對象釋放的適合也會被釋放。建議你在app中用強引用來鉗制所有新建的記憶體Realm資料庫實例。

2、數據模型

Realm的數據模型是用傳統的Objective-C介面(interface)和屬性(@property)定義的。 只要定義 RLMObject 的一個子類或者一個現成的模型類,你就能輕鬆創建一個Realm的數據模型對象。Realm模型對象和其他的Objective-c的功能很相似–你可以給它們添加你自己的方法和protocol然後和其他的對象一樣使用。 唯一的限制就是從它們被創建開始,只能在一個進程中被使用。 

如果已經安裝了Realm Xcode插件,在 New File 對話框中會有一個很漂亮的樣板,你可以用它來創建interface和implementation文件。 

用一個對象來表示一篇文章(Articl),創建的數據模型如下:

  • Article.h
@interface Article : RLMObject

@property NSString *num;//序號
@property NSString *title;//標題
@property NSString *link;//鏈接地址
@property NSString *author;//作者
@property NSString *tag;//標簽分類
@property NSInteger weight;//權重

@end

RLM_ARRAY_TYPE(Article)
  • Article.m
@implementation Article

//主鍵
+ (NSString *)primaryKey {
    return @"num";
}

//需要添加索引的屬性
+ (NSArray *)indexedProperties {
    return @[@"title"];
}

//預設屬性值
+ (NSDictionary *)defaultPropertyValues {
    return @{@"author":@"zengjing"};
}

//忽略的欄位
+ (NSArray *)ignoredProperties {
    return @[@"weight"];
}

@end

說明:

(1)Realm支持以下的屬性(property)種類:BOOL, bool, int, NSInteger, long, float, double, CGFloat, NSString, NSDate 和 NSData。

(2)你可以使用 RLMArray<Object> 和 RLMObject 來模擬對一或對多的關係(Realm也支持RLMObject繼承) 

(3)Realm忽略了Objective-C的property attributes(如nonatomic, atomic, strong, copy, weak 等等)。 所以,推薦在創建模型的時候不要使用任何的property attributes。但是,假如你設置了,這些attributes會一直生效直到RLMObject被寫入realm資料庫。

(4)定義了 RLM_ARRAY_TYPE(Article) 這個巨集表示支持 RLMArray<Article> 該屬性 

(5)另外Realm提供了以下幾個方法供對屬性進行自定義:

1) + (NSArray *)indexedProperties; : 可以被重寫來來提供特定屬性(property)的屬性值(attrbutes)例如某個屬性值要添加索引。 

2) + (NSDictionary *)defaultPropertyValues; : 為新建的對象屬性提供預設值。 

3) + (NSString *)primaryKey; : 可以被重寫來設置模型的主鍵。定義主鍵可以提高效率並且確保唯一性。 

4) + (NSArray *)ignoredProperties; :可以被重寫來防止Realm存儲模型屬性。 

3、數據增刪改查

(1)存儲數據

創建數據模型對象:

Article *article = [[Article alloc] init];
article.num      = @"1";
article.title    = @"iOS開發中集成Reveal";
article.link     = @"http://blog.devzeng.com/blog/ios-reveal-integrating.html";
article.tag      = @"iOS";

存儲數據:

RLMRealm *realm = [RLMRealm defaultRealm];
[realm beginWriteTransaction];
[realm addObject:article];
[realm commitWriteTransaction];

(2)刪除數據

1)刪除指定的數據:

- (void)deleteObject:(RLMObject *)object;

2)刪除一組數據:

- (void)deleteObjects:(id)array;

3)刪除全部的數據:

- (void)deleteAllObjects;

(3)修改數據

修改數據如果該條數據不存在則會新建一條數據。

1)針對單個數據進行的修改或新增:

- (void)addOrUpdateObject:(RLMObject *)object;

2)針對一組數據的修改或新增:

- (void)addOrUpdateObjectsFromArray:(id)array;

說明:對於增加、刪除、修改必須要在事務中進行操作。

(5)查詢數據

1)查詢全部數據

RLMResults *results = [Article allObjects];

或指定Realm資料庫:

NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *realmPath = [path stringByAppendingPathComponent:@"devzeng.realm"];
RLMRealm *realm = [RLMRealm realmWithPath:realmPath];
RLMResults *results = [Article allObjectsInRealm:realm];

2)條件查詢

假設要查詢所有分組是iOS和作者是zengjing的文章:

RLMResults *results = [Article objectsWhere:@"tag = 'iOS' AND author = 'zengjing'"];

也可以使用謂詞查詢:

NSPredicate *pred = [NSPredicate predicateWithFormat:@"tag = '%@' AND author = '%@'", @"iOS", @"zengjing"];
RLMResults *results = [Article objectsWithPredicate:pred];

3)條件排序

假設要查詢所有分組是iOS和作者是zengjing的文章,然後篩選出來的結果按照num欄位進行遞增排序:

RLMResults *results = [[Article objectsWhere:@"tag = 'iOS' AND author = 'zengjing'"] sortedResultsUsingProperty:@"num" ascending:YES];

4)鏈式查詢(結果過濾)

假設要查詢所有所屬分組是iOS的文章,然後從中篩選出作者是zengjing的數據:

RLMResults *results1 = [Article objectsWhere:@"tag = 'iOS'"];
RLMResults *results2 = [results1 objectsWhere:@"author = 'zengjing'"];

4、通知

每當一次寫事務完成Realm實例都會向其他線程上的實例發出通知,可以通過註冊一個block來響應通知:

self.token = [realm addNotificationBlock:^(NSString *note, RLMRealm * realm) {
    [_listTableView reloadData];
}];

只要有任何的引用指向這個返回的notification token,它就會保持激活狀態。在這個註冊更新的類里,你需要有一個強引用來鉗制這個token, 因為一旦notification token被釋放,通知也會自動解除註冊。

@property (nonatomic, strong) RLMNotificationToken *token;

另外可以使用下麵的方式解除通知:

[realm removeNotification:self.token];

5、資料庫版本遷移

當你和資料庫打交道的時候,時不時的你需要改變數據模型(model),但因為Realm中得數據模型被定義為標準的Objective-C interfaces,要改變模型,就像改變其他Objective-C interface一樣輕而易舉。舉個例子,假設有個數據模型 Person : 

在v1.0中數據模型如下:

// v1.0
@interface Person : RLMObject
@property NSString *firstName;
@property NSString *lastName;
@property int age;
@end

升級到v2.0之後將firstName和lastName欄位合併為一個欄位fullName

// v2.0
@interface Person : RLMObject
@property NSString *fullName; // new property
@property int age;
@end

遷移的邏輯可以為:

[RLMRealm setSchemaVersion:2.0 forRealmAtPath:[RLMRealm defaultRealmPath] 
                         withMigrationBlock:^(RLMMigration *migration, 
                                              NSUInteger oldSchemaVersion) {
  [migration enumerateObjects:Person.className 
                        block:^(RLMObject *oldObject, RLMObject *newObject) {
    if (oldSchemaVersion < 2.0) {
      newObject[@"fullName"] = [NSString stringWithFormat:@"%@ %@", oldObject[@"firstName"], oldObject[@"lastName"]];
    }
  }];
}];

當版本升級到3.0時,添加新的屬性email

// v3.0
@interface Person : RLMObject
@property NSString *fullName;
@property NSString *email;   // new property
@property int age;
@end

遷移的邏輯可以為:

[RLMRealm setSchemaVersion:2.0 forRealmAtPath:[RLMRealm defaultRealmPath] 
                         withMigrationBlock:^(RLMMigration *migration, 
                                              NSUInteger oldSchemaVersion) {
  [migration enumerateObjects:Person.className 
                        block:^(RLMObject *oldObject, RLMObject *newObject) {
    //處理v2.0的更新
    if (oldSchemaVersion < 2.0) {
      newObject[@"fullName"] = [NSString stringWithFormat:@"%@ %@", oldObject[@"firstName"], oldObject[@"lastName"]];
    }
    //處理v3.0的更新
    if(oldSchemaVersion < 3.0) {
      newObject[@"email"] = @"";
    }
  }];
}];

說明(摘自官方的FAQ)

1、realm的支持庫有多大?

一旦你的app編譯完成,realm的支持庫應該只有1MB左右。我們發佈的那個可能有點大(iOS ~37MB, OSX ~2.4MB), 那是因為它們還包含了對其他構架的支持(ARM,ARM64,模擬器的是X86)和一些編譯符號。 這些都會在你編譯app的時候被Xcode自動清理掉。

2、我應該在正式產品中使用realm嗎?

自2012年起,realm就已經開始被用於正式的商業產品中了。正如你預期,我們的objective-c & Swift API 會隨著社區的反饋不斷的完善和進化。 所以,你也應該期待realm帶給你更多的新特性和版本修複。

3、我要付realm的使用費用嗎?

不要, Realm的徹底免費的, 哪怕你用於商業軟體。

參考資料

1、 《Realm Document》

2、 《Realm資料庫基礎教程》


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 今天在熟悉項目的某個功能模塊時,查看mybatis的映射文件內發現這樣的一串sql: 因原來進行開發時,並沒有用到此函數 所以在網上查詢了一點資料 對leadover的解釋如下: 換句話說就是通過這個函數能拿到當前列之前的第n條數據 例子: 目前有如下內容的一張表: 執行之後是這樣的result: ...
  • 一.概述 隨著上線後,數據越來越多,很多sql語句開始顯露出性能問題,本章介紹在mysql中優化sql語句的方法。 1. 通過show status 命令瞭解各種sql的執行頻率 通過show [session | global] 命令可以提供伺服器狀態信息,也可以在操作系統上使用mysqladmi ...
  • 數據科學並沒有一個獨立的學科體系,統計學,機器學習,數據挖掘,資料庫,分散式計算,雲計算,信息可視化等技術或方法來對付數據。但從狹義上來看,我認為數據科學就是解決三個問題:1. data pre-processing;2. data interpretation;3.data modeling an ...
  • 配置hadoop: 第一個:hadoop-env.sh export JAVA_HOME=/usr/java/jdk1.7.0_65 選擇修改日誌文件目錄(預設目錄內日誌文件太多易混): export HADOOP_LOG_DIR=/var/log/hadoop 第二個:core-site.xml ...
  • 一. 概述 這次介紹實例級別資源等待LCK類型鎖的等待時間,關於LCK鎖的介紹可參考 “sql server 鎖與事務撥雲見日”。下麵還是使用sys.dm_os_wait_stats 來查看,並找出耗時最高的LOK鎖。 查出如下圖所示: 1. 分析介紹 重點介紹幾個耗時最高的鎖含義: LCK_M_I ...
  • MySQL基本簡單操作 現在我創建了一個數據表,表的內容如下: mysql select from gubeiqing_table; + + + | name | age | + + + | gbq | 21 | | zhangsan | 20 | | lisi | 22 | + + + 3 row ...
  • 解決之前層次不齊的排版截圖,如下圖: 解決之後的整齊排版截圖,如下圖: 今天忽然發現android項目中的文字排版參差不齊的情況非常嚴重,不得不想辦法解決一下。經過研究之後,終於找到了textview自動換行導致混亂的原這個問題是由於:半形字元與全形字元混亂所致!一般情況下,我們輸入的數字、字母以及 ...
  • 問題:scrollview內部組件都設置了android:layout_height="fill_parent"卻沒有效果。 解決辦法:設置scrollview的fillViewport屬性為"true"。 說明:需要設置scrollview的fillViewport屬性為"true"時,才能使其子 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...