realm 介紹及安裝
- 簡(jiǎn)介
Realm 是一個(gè)跨平臺(tái)的移動(dòng)終端數(shù)據(jù)庫,支持 iOS(Swift 和 Objective-C 語言都支持)和 Android。Realm 的目的就是提供比 SQLite 和 Core Data 更好更快的數(shù)據(jù)庫支持。它不僅僅是更好和更快,而且更加易于使用,短短幾行代碼就可以完成很多操作。Realm 完全免費(fèi),你可以隨意使用它。Realm 是為移動(dòng)設(shè)備而生的,因?yàn)樵谶^去的十年中,移動(dòng)終端的數(shù)據(jù)庫技術(shù)沒有任何的革新?,F(xiàn)在如果和移動(dòng)終端的數(shù)據(jù)庫打交道,你只有一種選擇,使用 SQLite 或者是底層封裝了 SQLite 的技術(shù)比如 Core Data。Realm 的目的是更加易用,它并不是一個(gè)建立在 SQLite 之上的 ORM,而是一個(gè)基于自己的持久化引擎,簡(jiǎn)單并且快速的面向?qū)ο笠苿?dòng)數(shù)據(jù)庫。
-
安裝
同絕大多數(shù)的第三方庫一樣,Realm也支持三種安裝方式:- 項(xiàng)目中直接添加xxx.framework <a >去下載</a>
- CocoaPods
- Charthge
具體安裝方式,可參考官方文檔:<a >Realm</a> 或 <a >Realm(中文說明)</a>
realm 插件及瀏覽器
-
Realm插件
使用Realm插件的好處是,可以直接使用xcode創(chuàng)建創(chuàng)建數(shù)據(jù)模型文件,基本格式也默認(rèn)搭建好了。
安裝方式:
下載 <a >release zip</a> 好后,打開文件中的plugin/RealmPlugin.xcodeproj并進(jìn)行編譯,重啟 Xcode之后插件即可生效。如果您使用 Xcode 菜單來建立一個(gè)新文件(File > New > File… — or ?N) ,您就可以看到有一個(gè)新建Realm模型的選項(xiàng)。效果如下:
Snip20170221_13.png Realm瀏覽器:Realm Browser
Realm Browser可以在appstore直接下載,因?yàn)槊赓M(fèi),所以,不用再通過任何第三方途徑下載安裝破解版的。
Realm Browser可以直接打開.realm的文件,或者直接雙擊.reaml文件也是默認(rèn)直接啟動(dòng)Realm Browser

realm 使用及創(chuàng)建
-
創(chuàng)建.realm文件
-
默認(rèn)文件
let reaml = try! Realm()這句代碼就表示在Docments中創(chuàng)建了一個(gè)
default.realm的文件。下面是Realm()初始化方法調(diào)用的方法,對(duì)大家應(yīng)該有收獲:public convenience init() throws { let rlmRealm = try RLMRealm(configuration: RLMRealmConfiguration.default()) self.init(rlmRealm)
}
```-
自定義文件
如果不想使用默認(rèn)的文件名default.realm或想自定義不同的.realm文件,那么看下面代碼:-
修改默認(rèn)的文件名:
// 數(shù)據(jù)庫的默認(rèn)地址在docments中 var config = Realm.Configuration() config.fileURL = config.fileURL!.deletingLastPathComponent().appendingPathComponent("name.realm") Realm.Configuration.defaultConfiguration = config -
自定義文件:
// 在docments中創(chuàng)建了一個(gè)Realm1.realm的文件 let realm1 = try! Realm(configuration: Realm.Configuration(fileURL: URL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!.appending("/Realm1.realm"))))
-
-
-
創(chuàng)建數(shù)據(jù)模型
-
模型支持的數(shù)據(jù)類型:
Realm支持以下的屬性類型:Bool、Int8、Int16、Int32、Int64、Double、Float、String、NSDate 以及NSData.
CGFloat 屬性被取消了,因?yàn)樗念愋筒灰蕾囉谄脚_(tái)。
String、NSDate 以及 NSData 類型的屬性都可以添加可選值。Object 類型的屬性必須設(shè)置為可選。存儲(chǔ)可空數(shù)字可以通過 Realm 可選值來實(shí)現(xiàn)。 -
創(chuàng)建模型:
Realm數(shù)據(jù)模型是基于標(biāo)準(zhǔn) Swift 類來進(jìn)行定義的,使用屬性來完成模型的具體定義。
通過簡(jiǎn)單的繼承 Object 或者一個(gè)已經(jīng)存在的模型類,您就可以創(chuàng)建一個(gè)新的 Realm 數(shù)據(jù)模型對(duì)象。
Realm模型對(duì)象在形式上基本上與其他 Swift 對(duì)象相同 - 您可以給它們添加您自己的方法(method)和協(xié)議(protocol),和在其他對(duì)象中使用類似。
主要的限制是某個(gè)對(duì)象只能在其被創(chuàng)建的那個(gè)線程中使用。
如果您安裝了我們的Xcode插件 ,那么可在”New File…“對(duì)話框中會(huì)有一個(gè)很漂亮的模板,可用來創(chuàng)建 Swift 文件。import RealmSwift // 狗狗的數(shù)據(jù)模型 class Dog: Object { dynamic var name = "" dynamic var owner: Person? // 屬性可以設(shè)置為可選 } // 狗狗主人的數(shù)據(jù)模型 class Person: Object { dynamic var name = "" dynamic var birthdate = NSDate(timeIntervalSince1970: 1) var dogs = List<Dog>() // let dogs = [Dog] () 包含了嵌套關(guān)系 }
-
realm 數(shù)據(jù)增加
- 單個(gè)
reaml.add(object: Object, update: Bool)
調(diào)用這個(gè)方法可以添加對(duì)應(yīng)的數(shù)據(jù),object是數(shù)據(jù),update,是指插入的數(shù)據(jù)是否覆蓋相同primaryKey的數(shù)據(jù),如果為true表示覆蓋,如果為false不覆蓋,默認(rèn)為false,這個(gè)屬性必須是唯一的。
class Dog: Object {
dynamic var type = ""
dynamic var name = ""
dynamic var age = 0
dynamic var id = ""
// 主鍵,唯一一行被標(biāo)記的屬性
override static func primaryKey()-> String {
return "age" // 必須是屬性,必須是不一樣的內(nèi)容
}
override static func ignoredProperties() -> [String] {
return ["type"]
}
}
// 實(shí)例化一個(gè)dog對(duì)象
let dog1 = Dog()
dog1.name = "dogName"
dog1.age = 1
dog1.id = "dog1"
// 獲取reaml
let reaml = try! Realm()
// 加入數(shù)據(jù)
try! reaml.write {
reaml.add(dog1,update: true)
}
-
多個(gè)
reaml.add(objects: [Object], update: Bool)
調(diào)用這個(gè)方法可以添加對(duì)應(yīng)的數(shù)據(jù),object是數(shù)據(jù),update,是指插入的數(shù)據(jù)是否覆蓋相同primaryKey的數(shù)據(jù),如果為true表示覆蓋,如果為false不覆蓋,默認(rèn)為false,這個(gè)屬性必須是唯一的。let dog1 = Dog() dog1.name = "dogName" dog1.age = 1 dog1.id = "dog1" let dog2 = Dog() dog2.name = "dogName" dog2.age = 2 dog2.id = "dog2" let dog3 = Dog() dog3.name = "Name" dog3.age = 3 dog3.id = "dog3" let dog4 = Dog() dog4.name = "dogName" dog4.age = 4 dog4.id = "dog4" let dog5 = Dog() dog5.name = "lastame" dog5.age = 5 dog5.id = "dog5" let reaml = try! Realm() try! reaml.write { reaml.add([dog1,dog2,dog3,dog4,dog5],update: true) }
realm 數(shù)據(jù)查找
如果您熟悉NSPredicate的話,那么您就能很容易掌握其在 Realm 中的查詢方法。Objects、Realm、List 以及 Results 都提供了方法,允許您通過簡(jiǎn)單地傳遞一個(gè) NSPredicate 實(shí)例、斷言字符串或者斷言格式化字符串來完成查詢這頂Object實(shí)例的操作,正如您在 NSArray 中執(zhí)行查詢的哪樣。
比如說,下面的例子就展示了如何通過從默認(rèn)的 Realm 數(shù)據(jù)庫中調(diào)用 Results().filter(_:...) 方法來檢索所有棕黃色,并且以“大”開頭命名的狗狗的:
// 使用斷言字符串查詢
var tanDogs = realm.objects(Dog).filter("color = '棕黃色' AND name BEGINSWITH '大'")
// 使用 NSPredicate 查詢
let predicate = NSPredicate(format: "color = %@ AND name BEGINSWITH %@", "棕黃色", "大")
tanDogs = realm.objects(Dog).filter(predicate)
查看蘋果的斷言編程指南來獲取更多關(guān)于斷言查詢和NSPredicate Cheatsheet的使用信息。 Realm 支持許多常見的斷言:
- 比較操作數(shù)(comparison operand)可以是屬性名稱或者某個(gè)常量,但至少有一個(gè)操作數(shù)必須是屬性名稱;
- 比較操作符 ==、<=、<、>=、>、!=, 以及 BETWEEN 支持 Int, Int8, Int16, Int32, Int64, Float, Double 以及 NSDate 屬性類型的比較,比如說 age == 45;
- 相等比較 ==以及!=,比如說Results<Employee>().filter("company == %@", company)
- 比較操作符 == and != 支持布爾屬性;
- 對(duì)于 String 和 NSData 屬性來說,我們支持 ==、!=、BEGINSWITH、CONTAINS 以及 ENDSWITH 操作符,比如說 name CONTAINS ‘Ja’;
- 字符串支持忽略大小寫的比較方式,比如說 name CONTAINS[c] ‘Ja’ ,注意到其中字符的大小寫將被忽略;
- Realm 支持以下復(fù)合操作符:“AND”、“OR” 以及 “NOT”。比如說 name BEGINSWITH ‘J’ AND age >= 32;
- 包含操作符 IN,比如說 name IN {‘Lisa’, ‘Spike’, ‘Hachi’};
- ==、!=支持與 nil 比較,比如說 Results<Company>().filter("ceo == nil")。注意到這只適用于有關(guān)系的對(duì)象,這里 ceo 是 Company 模型的一個(gè)屬性。
- 通過 ==, != 進(jìn)行空值比較,比如說 Results<Company>().filter("ceo == nil"); 注意,Realm 將 nil 視為一個(gè)特殊的值而不是“缺失值”,不像 SQL 那樣 nil 等于自身。
- ANY 比較,比如說 ANY student.age < 21 List 以及 Results 屬性支持集合表達(dá)式:@count、@min、@max、@sum 以及 @avg,例如 realm.objects(Company).filter("employees.@count > 5") 用以尋找所有超過 5 名雇員的公司。
- 支持子查詢,不過有限制:
@count 是唯一能應(yīng)用在 SUBQUERY 表達(dá)式中的操作符
SUBQUERY(…).@count 表達(dá)式必須與常量進(jìn)行比較
相關(guān)子查詢目前還不支持
realm 數(shù)據(jù)修改
Realm 提供了一系列用以更新數(shù)據(jù)的方式,這些方式都有著各自所適應(yīng)的情景。請(qǐng)選擇最符合您當(dāng)前需求的方式來使用:
- 內(nèi)容直接更新:
您可以在寫入事務(wù)中通過設(shè)置某個(gè)對(duì)象的屬性從而完成對(duì)象的更新操作。
// 在一個(gè)事務(wù)中更新對(duì)象
let author = ···
try! realm.write {
author.name = "托馬斯·品欽"
}
- 鍵值對(duì)更改:
Object、Result 以及 List都遵守鍵值編碼(Key-Value Coding)(KVC)機(jī)制。 當(dāng)您在運(yùn)行時(shí)才能決定哪個(gè)屬性需要更新的時(shí)候,這個(gè)方法是最有用的。
將 KVC 應(yīng)用在集合當(dāng)中是大量更新對(duì)象的極佳方式,這樣就可以不用經(jīng)常遍歷集合,為每個(gè)項(xiàng)目創(chuàng)建一個(gè)訪問器了。
let persons = realm.objects(Person)
try! realm.write {
// 修改一個(gè)對(duì)象的屬性
persons.first?.setValue(true, forKeyPath: "isFirst")
// 將每個(gè)人的 planet 屬性設(shè)置為“地球”
persons.setValue("地球", forKeyPath: "planet")
}
- 通過主鍵更新
如果您的數(shù)據(jù)模型中設(shè)置了主鍵的話,那么您可以使用Realm().add(_:update:)來更新對(duì)象,或者當(dāng)對(duì)象不存在時(shí)插入新的對(duì)象。
// 主鍵,唯一一行被標(biāo)記的屬性
override static func primaryKey()-> String {
return "age" // 必須是屬性,必須是不一樣的內(nèi)容
}
class Dog: Object {
dynamic var type = ""
dynamic var name = ""
dynamic var age = 0
dynamic var id = ""
// 主鍵,唯一一行被標(biāo)記的屬性
override static func primaryKey()-> String {
return "age" // 必須是屬性,必須是不一樣的內(nèi)容
}
override static func ignoredProperties() -> [String] {
return ["type"]
}
}
// 實(shí)例化一個(gè)dog對(duì)象
let dog1 = Dog()
dog1.name = "dogName"
dog1.age = 1
dog1.id = "dog1"
// 獲取reaml
let reaml = try! Realm()
// 直接更新
try! reaml.write {
reaml.add(dog1,update: true)
}
realm 數(shù)據(jù)刪除
通過在寫入事務(wù)中將要?jiǎng)h除的對(duì)象傳遞給 Realm().delete(_:) 方法,即可完成刪除操作。
// let cheeseBook = ... 存儲(chǔ)在 Realm 中的 Book 對(duì)象
// 在事務(wù)中刪除一個(gè)對(duì)象
try! realm.write {
realm.delete(cheeseBook)
}
// 刪除多個(gè)
let dogs = reaml.objects(Dog.self).filter("age=2")
try! reaml.write {
reaml.delete(dogs)
}
您也能夠刪除存儲(chǔ)在 Realm 中的所有數(shù)據(jù)。注意,Realm 文件的大小不會(huì)被改變,因?yàn)樗鼤?huì)保留空間以供日后快速存儲(chǔ)數(shù)據(jù)。
// 從 Realm 中刪除所有數(shù)據(jù)
try! realm.write {
realm.deleteAll()
}
realm 數(shù)據(jù)排序
Results 允許您指定一個(gè)排序標(biāo)準(zhǔn),從而可以根據(jù)一個(gè)或多個(gè)屬性進(jìn)行排序。比如說,下列代碼將上面例子中返回的狗狗根據(jù)名字升序進(jìn)行排序:
// 排序名字以“B”開頭的棕黃色狗狗
let sortedDogs = realm.objects(Dog.self).filter("color = 'tan' AND name BEGINSWITH 'B'").sorted(byProperty: "name")
realm 通知
Realm 實(shí)例將會(huì)在每次寫入事務(wù)提交后,給其他線程上的 Realm 實(shí)例發(fā)送通知:
// 獲取 Realm 通知
let token = realm.addNotificationBlock { notification, realm in
viewController.updateUI()
}
// 隨后---一般在deinit方法中調(diào)用
token.stop()
文檔參考:
<a >中文文檔 </a>
<a >英文文檔</a>
