如今我正在節食。我須要減一些體重由於在加利福尼亞的時候胖了好多 – 好吃的食物實在是太多了:)!我瀏覽了一下 iTunes Store 中的那些可以追蹤喝水記錄的應用,可是在我看來這些應用要麼看上去很糟糕,要麼交互實在是很爛。我想:若是我決定作一個應用,豈不是一舉兩得嗎 – 我又能寫一個我想要的應用,又能選擇使用 Realm 而不是 Core Data。因此我開工了。 html
你知道當我看完文檔、開始使用 Realm 框架的第一感受是什麼嗎?哇,這簡直真是太棒了!這些開發的傢伙作的簡直超棒! 數據庫
免責聲明:接下來所寫的僅僅只覆蓋了 Realm 框架中最基本的一部分。我建議大家接下來能夠去閱讀官方文檔來獲取更多的信息。在這兒我並不想向大家展現關於 Realm 框架的所有內容,由於這篇文章不可能像文檔同樣又臭又長,而且我本身也會避免這樣的問題發生。官方的文檔很是的棒,你在開工前能夠先讀一下它。 swift
個人這個案例並非很複雜而是很是簡單的。整個 app 只有兩個抽象模型(Model)類: Day 和DrinkLogEntry 。此外,這個 app 也須要這些功能:添加、更新、篩選和排序存儲的數據。正如我所說這是個簡單的 app 。接下來我會呈現 app 中的一些代碼片斷。 網絡
Realm 中沒有像 xcdatamodel-like 這樣的文件。抽象模型僅僅是繼承自 Object 類的文件。 閉包
/** 表示了用戶一天的生活。 Day 這個類的信息包含用戶所喝的水和他們的天天喝水的目標。 */ class Day: Object { dynamic var identifier: String! /// 表示一天的開始的時間戳(UTC+0 時區) dynamic var timestamp: NSTimeInterval = 0 /// 用戶所喝的水的量(毫升) dynamic var waterDrank: Float = 0 /// 用戶天天喝水的目標(毫升) dynamic var dailyGoal: Float = 0 // ml var drinkLogs = List<DrinkLogEntry>() convenience init(timestamp: NSTimeInterval) { self.init() self.timestamp = timestamp self.identifier = Day.convertTimestampIntoIdentifier(timestamp) } override class func primaryKey() -> String? { return "identifier" } override class func indexedProperties() -> [String] { return ["identifier"] } class func convertTimestampIntoIdentifier(timestamp: NSTimeInterval) -> String { return String(format: "%.0f", arguments: [timestamp]) } }
全部前有 dynamic 關鍵字的屬性都會被轉化成數據抽象層的一部分。Realm 也支持關係型數據。在這個例子中 Day 這個類中存在 drinkLogs 的一對多關係。一對一的關係就僅是類中的特定屬性了。 app
Realm 也支持從 Core Data 中遷移數據。當你須要遷移的時候,能夠定義一個閉包而且執行它,而後你就能順利地執行遷移屬性的全部步驟了(譯者注:如何從 Core Data 遷移到 Realm)。 框架
Realm 框架有不少 Core Data 中沒有的新特性(也有多是我沒找到,或者說我就是想提一下這點??)。第一點就是「索引屬性」了。你能夠定義須要被索引的屬性集合。當屬性個數比較小的時候,搜索會變得很快。這有助於性能的提高。 ide
接下來不得不提一下「主鍵」。你能夠定義抽象模型中的一個屬性做爲它的主鍵。這能保證更加有效地更新數據以及保證數據的惟一性。 性能
在我使用的這個例子中,主鍵和索引屬性將做爲「標識符」,被用於搜索和更新數據。 fetch
數據中也能夠有被忽略的屬性,那些屬性將不被持久化保存。
你可使用未被持久化過的抽象模型,並且這些數據能夠被持久化時,你能夠將它們寫入 Realm 中。比起 Core Data,這就是我爲何喜歡 Realm 更多一點 – 由於它可以很好地解決一些臨時數據的問題。
let day = Day(timestamp: timestamp) day.dailyGoal = MenuSettings().dailyGoal
爲了可以寫入 Realm 或者從 Realm 中讀取,你須要建立 Realm 實例:
let realm = try! Realm()
這是如何將數據添加到數據庫的方法:
try! realm.write { realm.add(day) }
我特別喜歡 Realm 中更新數據的方式。咱們假設一下有一部分數據是從網絡上下載的,而且他們被映射過並且已經加進了數據庫。在數據庫中已經存在的數據僅須要更新而不是再次添加。
func fetchAll(completion: [Day] -> Void) { /** 假設請求返回了 JSON 而且數據已經映射到了抽象數據層的 Day 類型。 建立的數據尚未存入數據庫 Realm 中。 數據的標識符是相等的時間戳。 */ let day1 = Day(timestamp: 0) let day2 = Day(timestamp: 86400) let day3 = Day(timestamp: 172800) completion([day1, day2, day3]) } func sync() { fetchAll { (days) -> Void in let realm = try! Realm() try! realm.write { /// 若是有相同的標識符,那麼它將會被更新。 realm.add(days, update: true) } } }
這是一種比手動查詢帶有相同標識符而後更新值域更好的方法。
若是更新的參數被置爲 false,那麼新的數據將具備和在數據庫中存在的數據相同的主鍵。異常會被拋出。
還有其餘一些方法來更新數據,在這篇文章中我就不涉及了。
這是如何獲得全部 Day 類型數據的方法:
let days = realm.objects(Day.self)
篩選數據也很簡單:
realm.objects(Day.self).filter("identifier == %@", dayIdentifier)
按照時間戳升序排列這些數據:
let days = realm.objects(Day.self).sorted("timestamp", ascending: true)
當你每次執行 object()、sorted() 和 filter() 後均會獲得一個 Results<T> 類型的數據。這能讓你對結果進行額外的篩選排序等操做 - 這功能很是的強大並且很是好使。
在下一個有更加複雜的數據模型的 app 中我還會使用 Realm 嗎?答案是確定的。由於整個框架使用起來很是的簡單、集成起來很是的快速,並且 Realm 提供了很是多並且強大的功能特性。
P.S. 這個 app 正在等待過審 :)
2015/12/06更新
這個應用上架了 - Water Intake
本文由 SwiftGG 翻譯組翻譯,已經得到做者翻譯受權,最新文章請訪問 http://swift.gg。