日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

手把手教你从Core Data迁移到Realm

發布時間:2025/3/18 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 手把手教你从Core Data迁移到Realm 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?

來源:一縷殤流化隱半邊冰霜 (@halfrost ) ??

鏈接:http://www.jianshu.com/p/d79b2b1bfa72

?

?

前言

?

看了這篇文章的標題,也許有些人還不知道Realm是什么,那么我先簡單介紹一下這個新生的數據庫。號稱是用來替代SQLite 和 Core Data的。Realm有以下優點:

?

  • 使用方便

    Realm并不是基于SQLite的對象關系映射數據庫。它是使用自己的持久化引擎,為簡單和速度而生。用戶們說,他們在數分鐘之內就上手了Realm,構建一個app只需要數小時,每個app開發時間至少節約數周的時間。

  • Realm比其他的對象關系映射型數據庫(Object Relational Mapping),甚至比原生的SQLite更加快,這都得益于它零拷貝的設計。看看iOS用戶和Android用戶都是怎么評價它的快的Twitter

  • 跨平臺

    Realm 支持 iOS 和 OS X (Objective?C & Swift) 和Android。你可以通過使用相同的model,共享Realm文件到各個平臺,Java,Swift,Objective-C。并且在全平臺可以使用相同的業務邏輯

  • 優秀的特性

    Realm支持先進的特性,如加密,圖形查詢,輕松的遷移。Realm的API是一個非常適合打造高響應的應用程序,并且Realm為我們提供方便的組件,以輕松構建復雜的用戶界面

  • 值得信任

    Realm已經獲得了銀行,醫療保健提供商,復雜的企業app,星巴克這些產品的青睞。

  • 社區驅動

    Realm是Github上星標最多的數據庫里面排名第四,僅次于Java 和 Cocoa 的repos。除了核心工程之外,Realm的社區已經編譯了上百個app插件和組件

  • 支持

    可以從Realm公司快速獲得官方的答案,去編譯和支持你的數據庫。Realm的團隊會在Github, StackOverflow, & Twitter回答大家的各種問題

  • ?

    下面再發3張令人驚喜的性能對比圖

    ?

    ?

    上圖是每秒能在20萬條數據中進行查詢后count的次數。realm每秒可以進行30.9次查詢后count。SQLite僅僅只有每秒13.6次查詢后的count,相對于Core Data只有可憐的1。

    ?

    ?

    在20萬條中進行一次遍歷查詢,數據和前面的count相似:Realm一秒可以遍歷20萬條數據31次,而RCore Data只能進行兩次查詢。 SQLite也只有14次而已。

    ?

    ?

    這是在一次事務每秒插入數據的對比,Realm每秒可以插入9.4萬條記錄,在這個比較里純SQLite的性能最好,每秒可以插入17.8萬條記錄。然而封裝了SQLite的FMDB的成績大概是Realm的一半,4.7萬,Core Data就更低了,只有可憐的1.8萬。

    ?

    從以上3張圖可以看出Realm優秀的特性。那么我們開始使用Realm吧。第一步就是把本地的數據庫換成Realm。

    ?

    下面是我翻譯的一篇手把手教程,那么讓我們趕緊通過教程,來把Core Data遷移到Realm吧。

    ?

    原文:https://realm.io/news/migrating-from-core-data-to-realm/

    ?

    譯文

    ?

    把一個使用core data框架作為數據庫存儲方式的app,遷移到Realm的確是一件很容易的事情。如果你現在有一個已經用了Core Data的app,并且考慮換成Realm,這個手把手教程正適合你!

    ?

    很多開發者在用戶界面,高度集成了Core Data(有時可能有上千行代碼),這時很多人會告訴你轉換Core Data到Realm可能會花數小時。Core Data和Realm兩者都是把你的數據當成Object看待,所以遷移通常是很直接的過程:把你已經存在的Core Data的代碼重構成使用Realm API的過程是很簡單的。

    ?

    遷移后,你會為Realm為你app帶來的易用性,速度快,和穩定性而感到興奮。

    ?

    1.移除Core Data Framework

    ?

    首先,如果你的app當前正在使用Core Data,你需要找出哪些代碼是包含了Core Data的代碼。這些代碼是需要重構的。幸運的是,這里有一個手動的方式去做這件事:你可以手動的在整個代碼里面搜索相關的代碼,然后刪除每個導入了Core Data頭文件聲明的語句

    ?

    #import

    //or

    @import CoreData;

    ?

    一旦這樣刪除以后,每一行使用了Core Data的將會報一個編譯錯誤,接下來,解決這些編譯錯誤只是時間問題。

    ?

    2.移除Core Data的設置代碼

    ?

    在Core Data中,對model objects的更改是要通過managed object context object來實現的。而managed object context objects又是被persistent store coordinator object創建的,它們兩者又是被managed object model object創建的。

    ?

    可以這么說,在你開始思考用Core Data讀取,或者寫入數據的時候,你通常需要在你的app中的某處去設置依賴的對象,暴露一些Core Data的方法給你的app邏輯使用。無論在你的application delegate中,全局的單例中,或者就是在inline實現中,這些地方都會存在大量的潛在的Core Data 設置代碼。

    ?

    當你準備轉換到Realm時,所有的這些代碼都可以刪掉。

    ?

    在Realm中,所有設置都在你第一次創建一個Realm object的時候就已經都完成了。當然也是可以手動去配置它,就像你指定Realm數據文件存儲在你的硬盤的哪個路徑下,這些完全都可以在runtime的時候去選擇的。

    ?

    RLMRealm *defaultRealm = [RLMRealm defaultRealm];

    //or

    let realm = Realm()

    ?

    感覺很好吧?

    ?

    3.遷移model文件

    ?

    在Core Data中,實用的那些類都是被定義成NSManagedObject的子類。這些object的接口都是很標準的,原始的類型(比如NSInteger 和 CGFloat)是不能被使用的,它們必須抽象成一個NSNumber對象。

    ?

    @interface Dog : NSManagedObject

    ?

    @property (nonatomic, copy) NSString *name;

    @property (nonatomic, strong) NSNumber *age;

    @property (nonatomic, strong) NSDate *birthdate;

    ?

    @end

    ?

    @implementation Dog

    ?

    @dynamic name;

    @dynamic age;

    @dynamic birthdate;

    ?

    @end

    ?

    把這些managed object subclasses轉換成Realm是非常簡單的:

    ?

    @interface Dog : RLMObject

    ?

    @property NSString *uuid;

    @property NSString *name;

    @property NSInteger age;

    @property NSDate *birthdate;

    ?

    @end

    ?

    @implementation Dog

    ?

    + (NSString *)primaryKey

    {

    ????return @"uuid";

    }

    ?

    + (NSDictionary *)defaultPropertyValues

    {

    ????return @{ @"uuid" : [[NSUUID UUID] UUIDString],

    ??????????????@"name" : @"",

    ??????????????@"birthdate" : [NSDate date]};

    }

    ?

    @end

    ?

    或者

    ?

    class Dog: Object {

    ????dynamic var uuid = NSUUID().UUIDString

    ????dynamic var name = ""

    ????dynamic var age = 0

    ????dynamic var birthdate = NSDate().date

    ?

    ????override static func primaryKey() -> String? {

    ????????return "uuid"

    ????}

    }

    ?

    完成!這是多么的簡單?

    ?

    看這些實現,還是有一些Realm的細節需要注意的。

    ?

    對于初次使用Realm的人來說,沒有必要去指定屬性關鍵字,Realm在內部已經管理了。所以這些類的頭文件看上去都很精簡。此外,Realm支持簡單的數據類型,比如NSInteger 和 CGFloat,所有所有的NSNumber都可以安全的刪除。

    ?

    另一方面,這有一些關于Realm model的聲明額外的說明。

    ?

  • Core Data objects通過內部的NSManagedObjectID屬性去唯一標識一個objects,Realm把這個留給開發者去完成。在上面的例子中,我們額外添加了一個名為uuid的屬性,然后通過調用 [RLMObject primaryKey]方法去作為這個class的唯一標識。當然,如果你的objects完全不需要唯一標識,這些都可以跳過。

  • 在寫數據的過程中(這個過程不會太長!),Realm不能處理nil的object的屬性。原因是,在[RLMObject defaultPropertyValues]這個類方法中給每個object在最初創建的時候,每個object屬性都定義了一系列default值。當然這只是暫時的,我們很高興的告訴你,在接下來的更新中,我們將會支持Realm object的屬性可以為nil。

  • ?

    4.遷移寫操作

    ?

    如果你不能保存你的數據,這肯定不是一個持久的方案!創建一個新的Core Data對象然后再簡單的修改一下它,需要下面這些代碼:

    ?

    //Create a new Dog

    Dog *newDog = [NSEntityDescription insertNewObjectForEntityForName:@"Dog" inManagedObjectContext:myContext];

    newDog.name = @"McGruff";

    ?

    //Save the new Dog object to disk

    NSError *saveError = nil;

    [newDog.managedObjectContext save:&saveError];

    ?

    //Rename the Dog

    newDog.name = @"Pluto";

    [newDog.managedObjectContext save:&saveError];

    ?

    相比之下,Realm保存的操作是略有不同的,但在相同的范圍內修改上面的代碼,仍然有相似的地方。

    ?

    //Create the dog object

    Dog *newDog = [[Dog alloc] init];

    newDog.name = @"McGruff";

    ?

    //Save the new Dog object to disk (Using a block for the transaction)

    RLMRealm *defaultRealm = [RLMRealm defaultRealm];

    [defaultRealm transactionWithBlock:^{

    ????[defaultRealm addObject:newDog];

    }];

    ?

    //Rename the dog (Using open/close methods for the transaction)

    [defaultRealm beginWriteTransaction];

    newDog.name = @"Pluto";

    [defaultRealm commitWriteTransaction];

    ?

    或者

    ?

    //Create the dog object

    let mydog = Dog()

    myDog.name = "McGruff"

    ?

    //Save the new Dog object to disk (Using a block for the transaction)

    Realm().write {

    ????realm.add(myDog)

    }

    ?

    //Rename the dog (Using open/close methods for the transaction)

    Realm().beginWrite()

    myDog.name = "Pluto"

    Realm().commitWrite()

    ?

    完成!我們的數據被保存了!

    ?

    明顯的不同是,在Realm中,一旦一個objects被添加到一個Realm object中,它就是不可被修改的。為了在修改屬性操作的后面執行,Realm object會被保存在一個寫的事務中。這種不能被修改的model,保證了在不同線程中讀/寫 object數據的情況下,數據的一致性。

    ?

    Core Data的實現確實可以改變屬性,然后調用save方法,對比Realm的實現,只是一些小小的不同罷了。

    ?

    5.遷移查詢

    ?

    另一方面,如果你不能檢索查詢你的數據,這肯定不是一個持久的方案!

    ?

    在Core Data的基礎實現中,它運用了fetch requests的概念去從硬盤檢索數據。一個fetch request object是被當成一個單獨的實例化對象去創建的,包含了一些額外的過濾參數,排序條件。

    ?

    NSManagedObjectContext *context = self.managedObjectContext;

    ?

    //A fetch request to get all dogs younger than 5 years old, in alphabetical order

    NSEntityDescription *entity = [NSEntityDescription

    ?????????????????????????????? entityForName:@"Dog" inManagedObjectContext:context];

    ?

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"age

    ?

    雖然這確實挺好,但是需要編寫大量的代碼!一些聰明的開發者就開發了一些library使這些代碼編寫的更加容易。比如MagicalRecord。

    ?

    對比這些,使用了Realm之后,這些查詢的等效代碼如下:

    ?

    RLMResults *dogs = [[Dog objectsWhere:@"age

    ?

    或者

    ?

    var dogs = Realm().objects(Dog).filter("age

    ?

    在一行調用了2個方法。對比Core Data將近10行代碼。

    ?

    當然,相同操作得到的結果是相同的(RLMResults 和 NSArray 基本類似),轉換到Realm,由于這些查詢都是很獨立的,所以查詢周圍的邏輯只需要重構很少的一部分代碼就可以了。

    ?

    6.遷移用戶數據

    ?

    一旦你所有代碼都遷移到Realm,這里還有一個突出的問題,你如何遷移所有用戶已經存在在他們設備上的數據,從Core Data遷移到Realm中?

    ?

    顯然,這是非常復雜的問題,它決定于你的app的功能,還有用戶的環境。你處理這種情況可能解決辦法每次都不一樣。

    ?

    目前,我們看到了2種情況:

    ?

  • 一旦你遷移到Realm,你可以重新導入Core Data framework到你的app,用原生的NSManagedObject objects去fetch你的用戶的Core Data數據,然后手動的把數據傳給Realm。你可以把這段遷移的代碼永久的留在app中,或者也可以經過非常充足的時間之后,再刪除掉。

  • 如果用戶數據不是不可替代的——舉個例子,如果是一些簡單的緩存信息,可以通過硬盤上的用戶數據重新生成的話,那么可以很簡單的就把Core Data數據直接清除掉,當用戶下次打開app的時候,一切從0開始。當然這需要經過非常謹慎的考慮,不然的話,會給很多人留下非常壞的用戶體驗。

  • ?

    最終,決定應該偏向于用戶。理想的情況是不要留下Core Data還連接著你的

    app,但是結果還是要取決于你的情況。好運!

    ?

    進一步的討論

    ?

    雖然在移植一個應用程序到Realm過程中,沒有真正重要的步驟,但是有一些額外的情況下,你應該知道:

    ?

    并發

    ?

    如果你在后臺線程做了一些比較重的操作,你可能會發現你需要在線程之間傳遞Realm object。在Core Data中允許你在線程之間傳遞managed objects(雖然這樣做不是最佳實踐),但是在Realm中,在線程中傳遞objects是嚴格禁止的,并且任何企圖這樣做的,都會拋出一個嚴重的異常。

    ?

    如此來說,對于下面這些情況,是件很容易的事情:

    ?

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{

    ????//Rename the dog in a background queue

    ????[[RLMRealm defaultRealm] transactionWithBlock:^{

    ????????dog.name = @"Peanut Wigglebutt";

    ????}];

    ?

    ????//Print the dog's name on the main queue

    ????NSString *uuid = dog.uuid;

    ????dispatch_async(dispatch_get_main_queue(), ^{

    ????????Dog *localDog = [Dog objectForPrimaryKey:uuid];

    ????????NSLog(@"Dog's name is %@", localDog.name);

    ????});

    });

    ?

    或者

    ?

    dispatch_async(queue) {

    ????//Rename the dog in a background queue

    ????Realm().write {

    ????????dog.name = "Peanut Wigglebutt"

    ????}

    ?

    ????//Print the dog's name on the main queue

    ????let uuid = dog.uuid

    ????dispatch_async(dispatch_get_main_queue()) {

    ????????let localDog = Realm().objectForPrimaryKey(Dog, uuid)

    ????????println("Dog's name is \\(localDog.name)")

    ????}

    }

    ?

    雖然Realm objects不能在線程間被傳遞,但是Realm properties的副本可以在線程中被傳遞。考慮到Realm從磁盤中檢索objects是非常快速的,如果只是簡單的通過新線程在存儲區中重新refetch相同的object,這只會造成很小的性能損失。在這個例子中,我們取了對象的主鍵的copy,然后把它從后臺隊列傳遞給主隊列,然后再通過它在主線程的上下文中重新獲取該對象。

    ?

    NSFetchedResultsController 的等效做法

    ?

    相比Core Data的所有缺點,可能使用Core Data最充足的理由就是NSFetchedResultsController——這是一個類,它可以檢測到數據存儲的變化,并且能自動的把這一變化展示到UI上。

    ?

    在寫這篇文章的時候,Realm還沒有相似的機制。雖然它可以注冊一個block,這個block會在數據源發生變化的時候被執行,但是這種”蠻力”的做法對大多數的UI來說都是不友好的。目前,如果你的UI代碼很依賴Realm,那么這種做法對你來說就像處理一個breaker一樣。

    ?

    Realm的cocoa工程師現在正在開發一套通知系統,當一些object的屬性被更改的時候,允許我們去注冊一個通知,來接收到這些改變。這些特性都會在Realm的Swift and Objective?C 的未來的更新版本中。

    ?

    在此期間,如果現有的通知block API還是沒有滿足你的需要,但是你還是需要當特定的property被更改了收到一個通知,這里推薦使用神奇的第三方庫,名字叫RBQFetchedResultsController,它能模仿上述功能。除此之外,你還可以通過在objects里面加入setter方法,當setter方法被調用的時候,發送一個廣播通知,這樣做也能實現相同的功能。

    ?

    結尾

    ?

    Core Data和Realm的在展示數據的時候都是通過model objects,由于這一相似性,得以讓我們從Core Data遷移到Realm時非常迅速,簡單(并且非常令人滿意!)。盡管開始看上去令人怯步,但是實際做起來,就是需要把每個Core Data的方法調用轉換成等價的Realm的方法,然后寫一個輔助類去幫你遷移用戶的數據。這些也都非常簡單。

    ?

    如果你在你的app中使用Core Data遇到了些困難,需要些更加簡單的解決辦法,我們強烈推薦你嘗試一下Realm,看看它是否適用于你。如果適用,請你告訴我們!

    ?

    感謝閱讀這篇文章。快去用Realm構建一個令人驚喜的app吧!在這些地方可以聯系到我們

    ?

    StackOverflow

    https://stackoverflow.com/questions/tagged/realm?sort=newest

    ?

    GitHub

    https://github.com/realm/realm-cocoa

    ?

    Twitter

    https://twitter.com/realm

    ?

    總結

    以上是生活随笔為你收集整理的手把手教你从Core Data迁移到Realm的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。