版本:Realm Swift 3.15.0
使用要求
- Xcode9.2或更高版本
- 目標平臺要iOS8或以上
安裝
有3種方式:Dynamic Framwork\CocoaPods\Carthage
我是用CocoaPods安裝的,說一下具體步驟。
- 首先要先安裝CocoaPods(1.1.0以上版本)
- 然後在終端運行$ pod repo update 讓 CocoaPods 更新realm的最新可用版本
- 項目路徑下終端運行$ pod init 新建Podfile文件(若已經有就不用新建了)
- 在Podfile文件添加 use_frameworks! 和 pod 'RealmSwift'
- 在終端運行$ pod install 進行安裝
- 打開.xcworkspace結尾的文件以啓動工程
Models模型
Realm的Model類必須繼承Object。
屬性必須使用 @objc dynamic var
特性,從而讓其能夠訪問底層數據庫的數據。
有3個例外,LinkingObjects \
List \
RealmOptional。這些屬性不能聲明爲動態屬性,
因爲泛型屬性無法在 Objective-C 運行時中正確表示,而這個運行時是用來對 dynamic
屬性進行動態調度的。這些屬性應當始終用 let
進行聲明。
import RealmSwift
class Person: Object {
//屬性必須使用 @objc dynamic var 特性,從而讓其能夠訪問底層數據庫的數據。
@objc dynamic var tmpID = 0
@objc dynamic var id = 0
@objc dynamic var name = ""
@objc dynamic var picture: Data? = nil //支持可選類型
let dogs = List<Dog>()
//設置主鍵--聲明主鍵允許對象的查詢和更新更加高效,並且會強制要求每個值保持唯一性。
//主鍵的值一旦寫入Realm便不能修改了
override static func primaryKey() -> String? {
return "id"
}
//設置索引屬性--會讓寫的操作稍微慢些, 但用equality和IN操作符查詢數據會更快.
//最好在特殊的情況下使用索引屬性,譬如希望能提升讀取數據的速度的情況。
override static func indexedProperties() -> [String] {
return ["name"]
}
//設置忽略屬性--不會保存在Realm數據庫中
//就像正常的屬性,但不支持使用任何realm中的功能,例如是查詢功能。但還是能通過KVO來觀察值的變化。
override static func ignoredProperties() -> [String] {
return ["tmpID"]
}
}
操作Realm對象
1)對象的自動更新
let person = Person()
person.name = "Fido"
mperson.age = 1
try! realm.write {
realm.add(person)
}
let targetPerson = realm.objects(Person.self).filter("age == 1").first
try! realm.write {
targetPerson!.age = 2
}
print("age of my dog: \(person.age)") // => 2
2)model類繼承
// Base Model
class Animal: Object {
@objc dynamic var age = 0
}
// 與Animal類組合的models
class Duck: Object {
@objc dynamic var animal: Animal? = nil
@objc dynamic var name = ""
}
class Frog: Object {
@objc dynamic var animal: Animal? = nil
@objc dynamic var dateProp = Date()
}
// 使用
let duck = Duck(value: [ "animal": [ "age": 3 ], "name": "Gustav" ])
Writes寫
- models:
class Dog: Object {
@objc dynamic var name = ""
@objc dynamic var color = ""
@objc dynamic var age = 0
}
class Human: Object {
@objc dynamic var name = ""
@objc dynamic var age = 0
let dogs = List<Dog>()
}
- writes (寫操作需要在transaction中)
//方法1 - 通過Dog的屬性創建
let myDog = Dog()
myDog.name = "栗子"
myDog.color = "black"
myDog.age = 3
//方法2 - 通過字典創建
let myOtherDog = Dog(value: ["name":"happy","color":"white","age":1])
//方法3 - 通過數組創建
let myThirdDog = Dog(value: ["dogy","brown",3])
//利用存在的Dog Object創建
let aPerson = Human(value: ["James", 20, [myDog, myOtherDog]])
//直接創建
let anotherPerson = Human(value: ["Jane", 30, [["Buster","yellow", 5], ["Buddy","purple", 6]]])
// Write - 把數據寫進realm數據庫
try! realm.write {
realm.add(myDog)
realm.add(myOtherDog)
realm.add(myThirdDog)
realm.add(aPerson)
realm.add(anotherPerson)
}
- 結果(通過Realm Browser查看,可以App Store直接下載):
Queries查詢
- 查詢整個表格(因爲realm中的查詢都是懶加載的,只有在訪問屬性時纔讀取數據,所以不用擔心會佔用太多內存)
//查詢整個Human表格 --> Results<Human>
let persons = realm.objects(Human.self)
- 通過filter查詢
//通過filter查詢1 --> Results<Dog>
let puppies = realm.objects(Dog.self).filter("age < 3")
//通過filter查詢2 --> Results<Dog>
let targetDogs = realm.objects(Dog.self).filter("age = 2 AND name BEGINSWITH '慄'")
- 通過NSPredicate查詢
//通過NSPredicate查詢 --> Results<Human>
let predicate = NSPredicate(format: "age = 23 AND name BEGINSWITH %@", "J")
let targetHuman = realm.objects(Human.self).filter(predicate)
Update更新 (更新操作需要在transaction中)
- 可在任何線程查詢或更新
//可在任何線程查詢或更新
DispatchQueue(label: "background").async {
autoreleasepool {
let realm = try! Realm()
let persons = realm.objects(Human.self)
try! realm.write {
//把name這列數據的第一個James更新爲James blunt(KeyPath是model中的變量)
persons.first?.setValue("James blunt", forKeyPath: "name")
//把age這列數據全部更新爲23
persons.setValue(23, forKeyPath: "age")
}
}
}
- 有主鍵的model可直接更新
let animal = Animal(value: [1,"elephant"])
try! realm.write {
//有主鍵的object可直接更新
realm.add(animal, update: true)
}
Delete刪除
- 刪除指定數據
let animal = Animal(value: [1,"elephant"])
try? realm.write {
realm.delete(animal)
}
- 刪除所有
try! realm.write {
realm.deleteAll()
}
Migration數據遷移
- 當你想更新數據模型,例如在模型Animal類中新增屬性age(原本只有id和name兩個屬性)。不僅要在model類中增加屬性,還要進行migration操作。
class Animal: Object {
@objc dynamic var id = 0
@objc dynamic var name = ""
@objc dynamic var age = 0
}
- migration操作 - 在AppDelegate.swift中的 didFinishLaunchingWithOptions 函數中操作。要更新數據模型時增加下面的版本號即可。
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let config = Realm.Configuration(
// 設置新的圖表版本. 一定要比之前的版本號要大,默認版本號是0.
schemaVersion: 1,
// 當打開低於上面版本realm數據庫時會自動調用這個遷移閉包
migrationBlock: { migration, oldSchemaVersion in
if (oldSchemaVersion < 1) {
// 不用做任何事,Realm會檢測新的屬性和移除舊的屬性,然後自動更新數據庫。
}
})
// 使默認Realm使用新的配置
Realm.Configuration.defaultConfiguration = config
return true
}
參考自最新官方文檔:https://realm.io/docs/swift/latest/