由于最近公司需要将项目用
Swift
改写,项目中需要大量使用数据库,之前OC
使用的是Core Data
,Core Data
使用起来确实十分的繁琐,故决定在Swift
中弃用,改用Realm
数据库,下面将使用方法记录下来方便以后查看。
Realm 的优点
Realm
不是基于 Core Data
,也不是基于 SQLite
封装构建的。它有自己的数据库存储引擎,下面说一下 Realm
的一些优点。
跨平台: 现在很多应用都是要兼顾
iOS
和Android
两个平台同时开发。如果两个平台都能使用相同的数据库,那就不用考虑内部数据的架构不同,使用Realm
提供的API
,可以使数据持久化层在两个平台上无差异化的转换。代码可以使用Swift
、Objective-C
以及Java
语言来编写。简单易用:
Core Data
和SQLite
冗余、繁杂的知识和代码足以吓退绝大多数刚入门的开发者,而换用Realm
,则可以极大地减少学习成本,立即学会本地化存储的方法。大部分常用的功能(比如插入、查询等)都可以用一行简单的代码轻松完成,毫不吹嘘的说,把官方最新文档完整看一遍,就完全可以上手开发了,这是 中文官方文档地址。可视化:
Realm
还提供了一个轻量级的数据库查看工具,在Mac Appstore
可以下载Realm Browser
这个工具,开发者可以查看数据库当中的内容,执行简单的插入和删除数据的操作。
Realm Swift 的安装
这是 Realm
的 GitHub 地址 ,其他方法我就不说了,我是用 CocoaPods
方式安装的,所以就只说 CocoaPods
的安装方法了。
运行
pod repo update
,以确保CocoaPods
能够获取到Realm
的最新版本。在你的
Podfile
中,添加use_frameworks!
和pod 'RealmSwift'
到你的主要和测试目标。如果你使用的是
Xcode 8
,那么将下面代码复制到你的Podfile
底部,以便在必要的时候更新Swift
的版本。
post_install do |installer| |
在终端运行
pod install
。采用
CocoaPods
生成的.xcworkspace
来运行工程。在需要使用
Realm Swift
的地方加入import RealmSwift
。
Realm Browser 的使用
先说一下 Realm Browser
这个数据库查看工具的使用方法。
1. 模拟器调试
- 如果是使用模拟器进行调试,首先通过以下代码打印出
Realm
数据库地址。
let realm = try! Realm() |
- 然后打开
Finder
按下command + shift + G
跳转到对应路径下,用Realm Browser
打开对应的.realm
文件就可以看到数据了。
2. 真机调试
- 如果是真机调试的话,打开
Xcode
,选择菜单Window
下的Devices
。
- 选择对应的设备与项目,点击
Download Container
。
- 导出
xcappdata
文件后,显示包内容,进到AppData
下的Documents
,使用Realm Browser
打开.realm
文件即可。
Realm Swift 的使用
1. 配置 Realm 数据库
- 将以下代码写在
AppDelegate
的didFinishLaunchingWithOptions
方法中,这个方法主要用于数据模型属性增加或删除时的数据迁移,每次模型属性变化时,将schemaVersion
加1
即可,Realm
会自行检测新增和需要移除的属性,然后自动更新硬盘上的数据库架构,移除属性的数据将会被删除。
/* Realm 数据库配置,用于数据库的迭代更新 */ |
- 如果属性改变后,想要保留原来已存在的数据来更新新的属性值,在属性变化后将
schemaVersion
加1
,并将config
改为如下,其余不变。
let config = Realm.Configuration(schemaVersion: schemaVersion, migrationBlock: { migration, oldSchemaVersion in |
- 如果是只是属性重命名,想保留原来已经存在的数据,重命名以后将
schemaVersion
加1
,并将config
改为如下,其余不变,并且重命名操作应该在调用上面enumerateObjects(ofType: _:)
之外完成。
let config = Realm.Configuration(schemaVersion: schemaVersion, migrationBlock: { migration, oldSchemaVersion in |
2. Model 数据模型
Realm
数据模型是基于标准 Swift
类来进行定义的,使用属性来完成模型的具体定义,Realm
模型对象在形式上基本上与其他 Swift
对象相同,你可以给它们添加您自己的方法和协议,和在其他对象中使用类似。
Realm 支持的属性类
Realm
支持这几种属性类型:Bool
、Int8
、Int16
、Int32
、Int64
、Double
、Float
、String
、NSDate
以及 NSData
,下面的表格提供了关于声明模型属性的简易参考。
类型 | 非可选值形式 | 可选值形式 |
---|---|---|
Bool | dynamic var value = false |
let value = RealmOptional<Bool>() |
Int | dynamic var value = 0 |
let value = RealmOptional<Int>() |
Float | dynamic var value: Float = 0.0 |
let value = RealmOptional<Float>() |
Double | dynamic var value: Double = 0.0 |
let value = RealmOptional<Double>() |
String | dynamic var value = "" |
dynamic var value: String? = nil |
Data | dynamic var value = NSData() |
dynamic var value: NSData? = nil |
Date | dynamic var value = NSDate() |
dynamic var value: NSDate? = nil |
Object | 必须是可选值 |
dynamic var value: Class? |
List | let value = List<Class>() |
必须是非可选值 |
LinkingObjects | let value = LinkingObjects(fromType: Class.self, property: "property") |
必须是非可选值 |
Model 数据模型创建
下面以 Dog
和 Person
为例,通过简单的继承 Object
或者一个已经存在的模型类,你就可以创建一个新的 Realm
数据模型对象。
普通的数据模型
/// 狗狗的数据模型 |
关系绑定
/// 狗狗的数据模型 |
反向关系
如果对多关系属性 Person.dogs
链接了一个 Dog
实例,而这个实例的对一关系属性 Dog.owner
又链接到了对应的这个 Person
实例,那么实际上这些链接仍然是互相独立的。
为 Person
实例的 dogs
属性添加一个新的 Dog
实例,并不会将这个 Dog
实例的 owner
属性自动设置为该 Person
。
但是由于手动同步双向关系会很容易出错,并且这个操作还非常得复杂、冗余,因此 Realm
提供了 链接对象 (linking objects)
属性来表示这些反向关系。
/// 狗狗的数据模型 |
索引属性(Indexed Properties)
重写 Object.indexedProperties()
方法可以为数据模型中需要添加索引的属性建立索引。Realm
支持字符串
、整数
、布尔值
以及 NSDate
属性作为索引。对属性进行索引可以减少插入操作的性能耗费,加快比较检索的速度(比如说 =
以及 IN
操作符)
/// 狗狗的数据模型 |
主键(Primary Keys)
重写 Object.primaryKey()
可以设置模型的主键。声明主键之后,对象将允许进行查询,并且更新速度更加高效,而这也会要求每个对象保持唯一性。 一旦带有主键的对象被添加到 Realm
之后,该对象的主键将不可修改。
Realm
可以将 Int
和 String
类型的属性设为主键,但是不支持自增长属性,所以只能自己给主键生成一个唯一的标识,可以使用 UUID().uuidString
方法生成唯一主键。
/// 狗狗的数据模型 |
忽略属性(Ignored Properties)
重写 Object.ignoredProperties()
可以防止 Realm
存储数据模型的某个属性。Realm
将不会干涉这些属性的常规操作,它们将由成员变量提供支持,并且您能够轻易重写它们的 setter
和 getter
。
/// 狗狗的数据模型 |
3. 创建数据模型对象
- 可以用多种方法创建一个新的对象:
/* (1) 创建一个狗狗对象,然后设置其属性 */ |
- 即使是数组以及字典的多重嵌套,
Realm
也能够轻松完成对象的创建。注意List
只能够包含Object
类型,不能包含诸如String
之类的基础类型。
/* 这里我们就可以使用已存在的狗狗对象来完成初始化 */ |
4. 数据库操作(增删改查)
任何操作都需要获取 Realm
实例,每个线程只需要使用一次即可。
/* 获取默认的 Realm 实例,每个线程只需要使用一次即可 */ |
增加数据
/* 创建一个 Dog 对象 */ |
删除数据
// let dog = ... 存储在 Realm 中的 Dog 对象 |
修改数据
- 内容直接更新: 在事务中直接修改某一条数据。
// let dog = ... 存储在 Realm 中的 Dog 对象 |
- ** 通过主键更新: ** 如果你的数据模型中设置了主键的话,那么你可以使用
Realm().add(_:update:)
来更新数据,如果数据不存在时会自动插入新的数据。
// let dog = ... 存储在 Realm 中的 Dog 对象(有主键) |
- 键值编码:
Object
、Result
以及List
都遵守 键值编码(Key-Value Coding) 机制。 当你在运行时才能决定哪个属性需要更新的时候,这个方法是最有用的。将KVC
应用在集合当中是大量更新对象的极佳方式,这样就可以不用经常遍历集合,为每个项目创建一个访问器了。
// let dogs = ... 存储在 Realm 中的多个 Dog 对象 |
查询数据
- 普通查询: 查询数据库中某张表的所有数据。
/* 从数据库中查询所有狗狗 */ |
- 主键查询: 根据
主键
查询某张表的某条数据,模型必须包含主键,否则会崩溃。
/* 从数据库中查询主键为 1 的狗狗 */ |
- 条件查询: 根据
断言字符串
或者NSPredicate 谓词
查询某张表中的符合条件数据。
/* 根据断言字符串从数据库查询 name 为 张三 的狗狗 */ |
- 排序查询: 将查询结果进行排序,可以和条件查询配合使用。
/* 将查询到的狗狗根据名字升序进行排序 */ |
想要了解更多可以查看 中文官方文档地址 ,有不足之处之后会补充,
OC
版本的话可以看这篇文章:Realm数据库 从入门到“放弃” ,写的非常详细,也参考了不少这篇文章的内容。