本文由我們團隊的郭杰童鞋分享秋泄。
Realm是什么
Realm是由Y Combinator公司孵化出來的一款可以用于iOS(同樣適用于Swift&Objective-C)和Android的跨平臺移動數(shù)據(jù)庫恳不。歷經(jīng)幾年才打造出來卖宠,為了徹底解決性能問題蕴忆,核心數(shù)據(jù)引擎用C++打造躏精,并不是建立在SQLite之上的ORM卫枝,所以Realm相比SQLite和CoreData而言更快惩系、更好、更容易去使用和完成數(shù)據(jù)庫的操作花費更少的代碼防楷。它旨在取代CoredData和sqlite,它不是對coreData的簡單封裝牺丙、相反的,Realm它使用了它自己的一套持久化存儲引擎。而且Realm是完全免費的冲簿,這不僅讓它變得更加的流行也使開發(fā)者使用起來沒有任何限制粟判。
Realm的特點
Realm以難以令人置信的快速和易用讓開發(fā)者能夠用僅僅幾行代碼完成你所需要的一切功能。它旨在打造讓用戶得在到移動領(lǐng)域離線時的最好體驗峦剔,我整理了Realm具有的如下特點:
- 易安裝:正如你在將要看到的使用Realm工作档礁。安裝Realm就像你想象中一樣簡單。在Cocoapods中使用簡單命令吝沫,你就可以使用Realm工作呻澜。
- 速度上:Realm是令人無法想象的快速使用數(shù)據(jù)庫工作的庫。Realm比SQLite和CoreData更快惨险,這里的數(shù)據(jù)就是最好的證明易迹。
- 跨平臺:Realm數(shù)據(jù)庫文件能夠跨平臺和可以同時在iOS和Andriod使用。無論你是使用Java, Objective-C, or Swift平道,你都可以使用你的高級模型。
- 可擴展性:在開發(fā)你的移動App特別是如果你的應用程序涉及到大量的用戶和大量的記錄時供炼,具有良好的可擴展性是非常重要的一屋。
- 好的文檔&支持:Realm團隊提供了可讀的,非常有組織的并且豐富的文檔袋哼。如果你遇到什么問題通過Twitter冀墨、GitHub或者Stackoverflow與他們交流。
- 可靠性:Realm已經(jīng)被巨頭公司使用在他們的移動App中涛贯,像Pinterest, Dubsmash, and Hipmunk诽嘉。
- 免費性:使用Realm的所有功能都是免費的。
- 懶加載:只有當你真正訪問對象的值時候才真正從磁盤中加載進來弟翘。
必備條件
- iOS7及以后, OS X 10.9及以后虫腋。
- 至少Xcode7.3及以后。
- Realm針對iOS分為兩部分稀余,一個是Swift版本悦冀,一個是Objective-C版本。
Realm安裝
- 動態(tài)Framework庫睛琳。直接下載最新Realm的release版本盒蟆,拖入項目工程中即可。
- CocoaPods管理工具师骗。使用CocoaPods0.39版本以及上历等。
- Carthage管理工具。使用Carthage 0.17.0版本及以上辟癌。
- 靜態(tài)Framework庫寒屯。直接下載最新Realm的release版本,拖入項目工程中即可愿待。
(注意:本文將重點講解使用CocoaPods的方式安裝Realm到項目中)
配置Xcode和所需的工具
在配置Xcode項目之前浩螺,請確保你的電腦上已經(jīng)安裝了CocoaPods靴患,因為我們會使用CocoaPods在項目中安裝Realm。如果你不熟悉CocoaPods要出,你可以查看給你的網(wǎng)上的相關(guān)教程鸳君。
現(xiàn)在創(chuàng)建一個新的工程,選擇"Single View Application"患蹂,命名為RealmDemo或者任何你想的名稱或颊。請確保創(chuàng)建的項目是Objective-C語言。現(xiàn)在在終端打開你的項目目錄并執(zhí)行如下的CocoaPods命令:
Pod init
然后传于,使用Xcode打開Podfile文件囱挑,向其中添加如下內(nèi)容:
接下來執(zhí)行Pod install命令去下載Realm安裝到項目中。完成之后沼溜,你將看到新的Xcode項目的workspace在Podfile文件被生成平挑。請打開Xcode的RealmDemo.xworkspace和不要打開xcodeproj。打開workspace之后系草,你將看到Pod相關(guān)文件已經(jīng)被集成進去了通熄。
現(xiàn)在Xcode已經(jīng)準備好可以使用Realm工作了,但是我們還將需要安裝如下工具為的是讓我們使用Realm更輕松找都,容易唇辨。
在Xcode中安裝Realm插件(僅僅用于Xcode8以下版本)
Realm團隊已經(jīng)提供了非常有用的Xcode插件,它將被使用在生成Realm的模型能耻。為了安裝插件赏枚,我們使用Alcatraz.對于那些不了解什么是Alcatraz的人來說,可以自行去搜索下,Alcatraz真的非常好用晓猛。為了安裝Alcatraz需要通過以下終端中的命令行并且重啟你的Xcode饿幅。
curl -fsSL https://raw.githubusercontent.com/supermarin/Alcatraz/master/Scripts/install.sh | sh
之后在Xcode中,選擇Window,就可以看到下拉列表中的Package Manager選項戒职,就表明已經(jīng)安裝成功诫睬。
在Xcode彈出窗口中選擇需要的插件或者模板,在搜索框中你可以搜索任何插件或者各種各樣的模板去自定義你的Xcode帕涌。在搜索框中輸入"Realm"和"RealmPlugin"插件將顯示出來摄凡,點擊進行安裝。
![](https://www.appcoda.com/wp-content/uploads/2015/10/realm-plugin.png)
Realm瀏覽器
除了以上的工具和插件之外蚓曼,還有一個就是Realm瀏覽器亲澡。這個瀏覽器可以幫助你去閱讀和編輯你的.realm數(shù)據(jù)庫文件。這些文件是在你的應用程序中被創(chuàng)建出來的纫版,它包含了關(guān)于數(shù)據(jù)庫表中實體床绪、屬性和記錄的信息。目前直接在Mac App Store中搜索Realm Browser進行下載即可。下載完成后癞己,打開Realm瀏覽器選擇Tools-> Generate demo database膀斋。它將為你生成測試數(shù)據(jù)庫文件和你可以打開它看到里面的數(shù)據(jù)。當你打開你的demo database時你應該看到
正如你看到的Class RealmTestClass1,它有1000個記錄和它展示了不同的列數(shù)據(jù)痹雅。接下來我們將討論Realm模型支持的屬性類型仰担。
Realm的數(shù)據(jù)庫創(chuàng)建
目前Realm提供了3種方式創(chuàng)建數(shù)據(jù)庫對象,一種是存儲在默認路徑下的數(shù)據(jù)庫绩社,一種是我們可以指定自己指定數(shù)據(jù)庫文件的存儲路徑和只讀屬性摔蓝,還有一種可以使用內(nèi)存數(shù)據(jù)庫。
- 默認Realm數(shù)據(jù)庫
RLMRealm *realm = [RLMRealm defaultRealm];
- 自定義數(shù)據(jù)庫(名稱愉耙、路徑)
//注意:新版本中關(guān)于配置Relam的文件路徑包括名稱等等都是在RLMRealmConfiguration對象中完成贮尉。
RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
// Use the default directory, but replace the filename with the username
config.fileURL = [[[config.fileURL URLByDeletingLastPathComponent]
URLByAppendingPathComponent:username]
URLByAppendingPathExtension:@"realm"];
// Set this as the configuration used for the default Realm
[RLMRealmConfiguration setDefaultConfiguration:config];
或者是
NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *dbPath = [docPath stringByAppendingPathComponent:@"guojie.realm"];
RLMRealm *realm1 = [RLMRealm realmWithURL:url];
當然了,RLMRealmConfiguration對象中還可以設(shè)置是否只讀數(shù)據(jù)庫
RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
// Get the URL to the bundled file
config.fileURL = [[NSBundle mainBundle] URLForResource:@"MyBundledData" withExtension:@"realm"];
// Open the file in read-only mode as application bundles are not writeable
config.readOnly = YES;
- 內(nèi)存數(shù)據(jù)庫
正常的Realm數(shù)據(jù)庫是存儲在硬盤上的朴沿,但是我們可以通過在RLMRealmConfiguration中設(shè)置inMemoryIdentifier屬性來創(chuàng)建一個內(nèi)存數(shù)據(jù)庫猜谚。
RLMRealmConfiguration *cfg = [RLMRealmConfiguration defaultConfiguration];
cfg.inMemoryIdentifier = @"test";
RLMRealm *realm = [RLMRealm realmWithConfiguration:cfg error:nil];
注意:內(nèi)存數(shù)據(jù)庫在每次程序退出時不會保存數(shù)據(jù)。如果某個內(nèi)存Realm實例沒有被引用赌渣,所有的數(shù)據(jù)在實例對象釋放的適合也會被釋放龄毡。建議你在app中用強引用來鉗制所有新建的內(nèi)存Realm數(shù)據(jù)庫實例。
Realm的構(gòu)建數(shù)據(jù)模型
Realm的數(shù)據(jù)模型是用傳統(tǒng)的 Objective-C 接口(interface)和屬性(@property)定義的锡垄。 只要定義 RLMObject的一個子類或者一個現(xiàn)成的模型類,你就能輕松創(chuàng)建一個Realm的數(shù)據(jù)模型對象祭隔。Realm模型對象和其他的Objective-C的功能很相似–你可以給它們添加你自己的方法和protocol然后和其他的對象一樣使用货岭。 唯一的限制就是從它們被創(chuàng)建開始,只能在一個進程中被使用疾渴。如果你已經(jīng)安裝了Xcode Plugin(Xcode版本<8.0)千贯,你將直接很方便在Xcode中的New File對話框中選擇Realm Model Object類的模板創(chuàng)建。你可以用它來創(chuàng)建interface和implementation文件搞坝。廢話不說搔谴,直接上代碼。
現(xiàn)在一起來使用Xcode中的Realmh插件去創(chuàng)建Realm類桩撮。打開Xcode和創(chuàng)建新文件敦第。在右邊框中選擇Realm:
![](https://www.appcoda.com/wp-content/uploads/2015/10/realm_model.png)
然后選擇名稱為Dog類名的Objective-C文件。現(xiàn)在你應該看到如下信息:
用一個Dog對象來表示一條小狗店量,緊接向類中添加屬性芜果。然后類在添加屬性之后向如下這樣:
- Dog.h
@interface Dog : RLMObject
/** 名字 */
@property (nonatomic, copy) NSString *name;
/** 年齡 */
@property (nonatomic, assign) NSInteger age;
/** 品種 */
@property (nonatomic, copy) NSString *type;
RLM_ARRAY_TYPE(Dog)
@end
- Dog.m
@implementation Dog
/**
設(shè)置主鍵
*/
+ (NSString *)primaryKey{
return @"numId";
}
/**
添加索引的屬性
*/
+ (NSArray<NSString *> *)indexedProperties{
return @[@"name"];
}
/**
添加默認值
*/
+ (NSDictionary *)defaultPropertyValues{
return @{@"type":@"taidi"
};
}
@end
說明:
Realm支持的屬性類型如下:BOOL, bool, int, NSInteger, long, float, double, CGFloat, NSString, NSDate 和 NSData。
你可以使用RLMArray<Object>和RLMObject來模擬對一或?qū)Χ嗟年P(guān)系(Realm也支持RLMObject繼承)
Realm忽略了Objective-C的property attributes(如nonatomic, atomic, strong, copy, weak 等等)融师。 所以右钾,推薦在創(chuàng)建模型的時候不要使用任何的property attributes。但是,假如你設(shè)置了舀射,這些attributes會一直生效直到RLMObject被寫入realm數(shù)據(jù)庫窘茁。
定義了RLM_ARRAY_TYPE(Dog) 這個宏表示支持RLMArray<Dog>該屬性
-
另外Realm提供了以下幾個方法供對屬性進行自定義:
-
+ (NSArray<NSString *> *)indexedProperties
: 可以被重寫來來提供特定屬性(property)的屬性值(attrbutes)例如某個屬性值要添加索引。 -
+ (nullable NSDictionary *)defaultPropertyValue
: 為新建的對象屬性提供默認值脆烟。 -
+ (nullable NSString *)primaryKey
: 可以被重寫來設(shè)置模型的主鍵山林。定義主鍵可以提高效率并且確保唯一性。 -
+ (nullable NSArray *)ignoredProperties
:可以被重寫來防止Realm存儲模型屬性浩淘。 -
- (void)transactionWithBlock:(__attribute__((noescape)) void(^)(void))block
:自動更新對象數(shù)據(jù)捌朴。 -
+ (NSArray<NSString *> *)requiredProperties
:可選屬性
-
Realm的數(shù)據(jù)增刪改查
存儲數(shù)據(jù)
(1).創(chuàng)建Dog對象,依次設(shè)置各個屬性
Dog *myDog = [[Dog alloc]init];
myDog.numId = @"1";
myDog.name = @"haha";
myDog.age = 10;
myDog.type = @"taidi";
(2).使用字典創(chuàng)建Dog對象
Dog *myDog2 = [[Dog alloc]initWithValue:@{@"numId":@"2",
@"name" :@"xiaoxiao",
@"age" :@11,
@"type" :@"heibei"
}];
(3).使用數(shù)組創(chuàng)建Dog對象
Dog *myDog3 = [[Dog alloc]initWithValue:@[@"3",@"小小",@12,@"smy"]];
(4).除此之外张抄,還支持嵌套的對象
如果在對象的屬性中有RLMObjects對象或者RLMArrays對象砂蔽,在這種情況下當你使用字典或者數(shù)組途徑創(chuàng)建對象時,你就可以使用數(shù)組或者字典對象替換屬性來表示它的屬性署惯。例如下面的嵌套對象例子:
// Instead of using already existing dogs...
Person *person1 = [[Person alloc] initWithValue:@[@"Jane", @30, @[aDog, anotherDog]]];
// ...we can create them inline
Person *person2 = [[Person alloc] initWithValue:@[@"Jane", @30, @[@[@"Buster", @5],
@[@"Buddy", @6]]]];
說明:
1. 最明顯的是使用指定的初始化程序創(chuàng)建一個對象左驾。注意被設(shè)置為必須的屬性在被添加之前一定要被設(shè)置值。
2. 對象可以通過傳入與屬性名稱一樣的字典Key和Values來創(chuàng)建极谊。
3. 最后诡右,對象可以使用數(shù)組創(chuàng)建,需要注意的是在數(shù)組中值的順序必須跟Model中相應屬性順序保持一致轻猖。
4. 需要注意的是: RLMArray僅僅只能包含RLMObject對象帆吻,而不包括基本數(shù)據(jù)類型例如NSString。
(5).存儲數(shù)據(jù)到Realm中
RLMRealm *realm = [RLMRealm defaultRealm];
[realm beginWriteTransaction];
[realm addObject:myDog];
[realm commitWriteTransaction];
請注意:當你同時執(zhí)行多個寫入操作時咙边,它們將會阻礙執(zhí)行的所在線程猜煮。所以你應該考慮在單獨的線程中處理而不是UI線程。另一個就是败许,當你在執(zhí)行寫入操作時王带,讀取操作不會被阻塞。這一點是很有用的市殷,因為你的App可以執(zhí)行許多讀取操作時在后臺同一時間寫入事務(wù)可能也會在后臺執(zhí)行中愕撰。
刪除數(shù)據(jù)
- 刪除指定的數(shù)據(jù):
- (void)deleteObject:(RLMObject *)object;
- 刪除一組數(shù)據(jù):
- (void)deleteObjects:(id)array;
- 刪除全部數(shù)據(jù):
- (void)deleteAllObjects;
修改數(shù)據(jù)
如果該條數(shù)據(jù)不存在則會新家一條數(shù)據(jù)。
- 針對單條數(shù)據(jù)進行的修改或新增:
- (void)addOrUpdateObject:(RLMObject *)object;
- 針對一組數(shù)據(jù)的修改或新增:
- (void)addOrUpdateObjectsFromArray:(id)array;
- 針對帶有主鍵的數(shù)據(jù)修改或新增
如果你的模型類中包含一個主鍵醋寝,Realm可以智能的以這個主鍵來更新或添加數(shù)據(jù)搞挣。
- (void)addOrUpdateObject:(RLMObject *)object;
- 使用KVC修改數(shù)據(jù)
如果你是一個iOS開發(fā)者,你將很熟悉KVC,Realm類中例如對象音羞、結(jié)果集柿究、list也是兼容KVC的。這樣可以幫助你利用runtime設(shè)置/更新屬性黄选∮看看這個例子:
RLMResults<Dog *> *dogs = [Dog allObjects];
[[RLMRealm defaultRealm] transactionWithBlock:^{
[[Dog firstObject] setValue:@20 forKeyPath:@"age"];
// set each person's name property to "wangwu"
[dogs setValue:@"wangwu" forKeyPath:@"name"];
}];
說明:對于增加婶肩、刪除、修改必須要在事務(wù)中進行操作貌夕。
查詢數(shù)據(jù)
查詢會返回RLMResults結(jié)果集律歼,它里面包含了RLMObject對象的集合。RLMResults的接口方法非常類似于NSArray一樣可以使用下標索引訪問元素啡专。與NSArray不同的是险毁,RLMResults的元素類型只有單一的RLMObject的子類型。所有的查詢都是懶查詢们童,即只有當訪問屬性時畔况,數(shù)據(jù)才會被讀取出來。查詢的結(jié)果不是拷貝本地磁盤中的數(shù)據(jù)而是直接原始數(shù)據(jù)慧库,所以修改某一處的數(shù)據(jù)將會直接修改磁盤中的數(shù)據(jù)跷跪。在結(jié)果集被使用的過程中,查詢的執(zhí)行是會被延遲的齐板。這意味著鏈接幾個臨時中間的RLMResults所進行的排序和過濾數(shù)據(jù)的操作不執(zhí)行額外的工作去處理中間的狀態(tài)吵瞻。一旦查詢已經(jīng)被執(zhí)行或者通知block已經(jīng)被添加,RLMResult在可能的情況下在后臺線程上執(zhí)行查詢以保證RLMResult的結(jié)果始終是Relam中最新的甘磨。
- 查詢?nèi)繑?shù)據(jù)
RLMResults<Dog *> *dogs = [Dog allObjects];
或者指定Realm數(shù)據(jù)庫:
NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *realmPath = [path stringByAppendingPathComponent:@"guojie.realm"];
RLMRealm *realm = [RLMRealm realmWithPath:realmPath];
RLMResults *results = [Dog allObjectsInRealm:realm];
在條件查詢中橡羞,如果你熟悉謂詞,那么你已經(jīng)知道該如何查詢了济舆。RLMObjects, RLMRealm, RLMArray, and RLMResults都提供了允許讓你通過傳遞一個謂詞實例卿泽、謂詞字符串、謂詞格式字符串來查詢具體RLMObject實例的方法滋觉。
- 條件查詢
假設(shè)要查詢名字是guojie和年齡是10的dog對象:
RLMResults *results = [Dog objectsWhere:@"name = 'haha' AND age = 10"];
也可以使用謂詞查詢:
NSPredicate *pred = [NSPredicate predicateWithFormat:@"type = '%@' AND name = '%@'", @"taidi", @"haha"];
RLMResults *results = [Dog objectsWithPredicate:pred]
- 條件排序
假設(shè)已經(jīng)查詢出type是taidi签夭,name是haha的數(shù)據(jù)結(jié)果集后,需要將結(jié)果按照num字段進行遞減排序:
NSPredicate *pred = [NSPredicate predicateWithFormat:@"type = '%@' AND name = '%@'", @"taidi", @"haha"];
RLMResults *results = [Dog objectsWithPredicate:pred];
results = [results sortedResultsUsingProperty:@"numId" ascending:NO];
請注意:結(jié)果集的順序只能保證在查詢排序時保持一致椎瘟,出于性能的原因,查詢順序不保證被保存侄旬。如果你需要為何查詢的順序肺蔚,則需要其他一些解決方案。
- 鏈式查詢(結(jié)果過濾)
假設(shè)要查詢的還是type是taidi,name是haha的結(jié)果集儡羔,還可以這樣處理:
RLMResults *results1 = [Dog objectsWhere:@"type = 'taidi'"];
RLMResults *results2 = [results1 objectsWhere:@"name = 'haha'"];
通知
每當一次寫事務(wù)完成Realm實例都會向其他線程上的實例發(fā)出通知宣羊,可以通過注冊一個block來響應通知:
self.token = [realm addNotificationBlock:^(NSString *note, RLMRealm * realm) {
[_listTableView reloadData];
}];
只要有任何的引用指向這個返回的notification token,它就會保持激活狀態(tài)汰蜘。在這個注冊更新的類里仇冯,你需要有一個強引用來鉗制這個token, 因為一旦notification token被釋放族操,通知也會自動解除注冊苛坚。
@property (nonatomic, strong) RLMNotificationToken *token;
另外可以使用下面的方式解除通知:
[realm removeNotification:self.token];
Realm版本遷移
當你和數(shù)據(jù)庫打交道的時候比被,你需要改變數(shù)據(jù)模型(Model),但是因為Realm中的數(shù)據(jù)模型被定義為標準的Objective-C interfaces,要改變模型泼舱,就像改變其他Objective-C interface一樣輕而易舉等缀。舉個例子,假設(shè)有個數(shù)據(jù)模型Person:
@interface Person : RLMObject
@property NSString *firstName;
@property NSString *lastName;
@property int age;
@end
當我們想添加一個字段fullName屬性而不是first和last names時娇昙,我們可以這樣做:
@interface Person : RLMObject
@property NSString *fullName;
@property int age;
@end
接下來執(zhí)行遷移:
// Inside your [AppDelegate didFinishLaunchingWithOptions:]
RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
config.schemaVersion = 1;
config.migrationBlock = ^(RLMMigration *migration, uint64_t oldSchemaVersion) {
//如果從沒遷移過尺迂,oldSchemaVersion == 0
if (oldSchemaVersion < 1) {
// The enumerateObjects:block: method iterates
// over every 'Person' object stored in the Realm file
[migration enumerateObjects:Person.className
block:^(RLMObject *oldObject, RLMObject *newObject) {
// 設(shè)置新增屬性的值
newObject[@"fullName"] = [NSString stringWithFormat:@"%@ %@",
oldObject[@"firstName"],
oldObject[@"lastName"]];
}];
}
};
[RLMRealmConfiguration setDefaultConfiguration:config];
在遷移的過程中重命名屬性名稱
// Inside your [AppDelegate didFinishLaunchingWithOptions:]
RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
config.schemaVersion = 1;
config.migrationBlock = ^(RLMMigration *migration, uint64_t oldSchemaVersion) {
// We haven’t migrated anything yet, so oldSchemaVersion == 0
if (oldSchemaVersion < 1) {
// The renaming operation should be done outside of calls to `enumerateObjects:`.
[migration renamePropertyForClass:Person.className oldName:@"yearsSinceBirth" newName:@"age"];
}
};
[RLMRealmConfiguration setDefaultConfiguration:config];
JSON
Realm并沒有直接的支持JSON,但是它可以使用[NSJSONSerialization JSONObjectWithData:options:error:]轉(zhuǎn)化之后的結(jié)果。在結(jié)合標準的API中的createOrUpdateInRealm方法就可以解決冒掌。
// A Realm Object that represents a city
@interface City : RLMObject
@property NSString *name;
@property NSInteger cityId;
// other properties left out ...
@end
@implementation City
@end // None needed
NSData *data = [@"{\"name\": \"San Francisco\", \"cityId\": 123}" dataUsingEncoding: NSUTF8StringEncoding];
RLMRealm *realm = [RLMRealm defaultRealm];
// 插入包含JSON的NSData數(shù)據(jù)
[realm transactionWithBlock:^{
id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];
[City createOrUpdateInRealm:realm withValue:json];
}];
說明:如果在JSON中包含有嵌套的對象或數(shù)組噪裕,那么會被自動被映射到一對多關(guān)系相關(guān)的嵌套對象中。
多線程訪問Realm
當需要從多線程去訪問同一個Realm時股毫,你必須初始化一個新的Realm膳音,去得到在App中每一個線程有一個不同的實例。只要你指定相同的Realm配置皇拣,那么所有的Realm實例將指向磁盤上的同一個文件严蓖。Realm是不支持在線程之間共享Relam實例的。當在一個單一事務(wù)中通過批量處理來寫入非常大的數(shù)據(jù)氧急,使用多線程是非常有用的颗胡。為了避免阻塞主線程,寫入事務(wù)可以放在使用GCD在后臺進行吩坝。Realm對象不是線程安全的毒姨,所有決定了不能線程間共享。因此你必須在你想要讀取或者寫入的每一個線程中獲取到Realm的對象實例钉寝。如下是在后臺隊列中插入100萬個對象的例子:
dispatch_async(queue, ^{
@autoreleasepool {
// Get realm and table instances for this thread
RLMRealm *realm = [RLMRealm defaultRealm];
// Break up the writing blocks into smaller portions
// by starting a new transaction
for (NSInteger idx1 = 0; idx1 < 1000; idx1++) {
[realm beginWriteTransaction];
// Add row via dictionary. Property order is ignored.
for (NSInteger idx2 = 0; idx2 < 1000; idx2++) {
[Person createInRealm:realm
withValue:@{@"name" : randomString,
@"birthdate" : randomDate}];
}
// Commit the write transaction
// to make this data available to other threads
[realm commitWriteTransaction];
}
}
});
總結(jié)
Realm是非常適合去管理本地存儲和數(shù)據(jù)庫弧呐。Realm給了你代碼層面非常強大的可擴展性和力量。對于大多數(shù)App甚至是游戲嵌纲,我認為你是需要使用數(shù)據(jù)庫俘枫,Realm值得你去使用。