iOS中Realm數據庫的基本用法


主題  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數據庫基礎教程》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM