版本: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/