Realm是一个跨平台的移动数据库引擎,目前支持iOS、Android平台,同时支持Objective-C、Swift、Java、React Native、Xamarin等多种编程语言
Realm并不是对SQLite或者CoreData的简单封装, 是由核心数据引擎C++打造,是拥有独立的数据库存储引擎,可以方便、高效的完成数据库的各种操作
Realm的优势与亮点
开源。Realm移动端数据库相关代码已全部开源。数千开发者在GitHub上参与了相关工作。另外还有几百个Realm数据库相关的扩展。 简单易用:Core Data、SQLite庞大的学习量和繁杂的代码足以吓退绝大多数刚入门的开发者,而换用Realm,则可以极大地减少学习代价和学习时间,让应用及早用上数据存储功能 跨平台:现在绝大多数的应用开发并不仅仅只在iOS平台上进行开发,还要兼顾到Android平台的开发。为两个平台设计不同的数据库是不明智的,而使用Realm数据库,iOS和Android无需考虑内部数据的架构,调用Realm提供的API就可以完成数据的交换 线程安全。程序员无需对在不同线程中,对数据库的读取一致性做任何考虑,Realm会保证每次读取都得到一致的数据
可视化工具Realm Studio
为了配合Realm的使用,Realm还提供了一个轻量级的数据库查看工具Realm Studio,借助这个工具,开发者可以查看数据库当中的内容,并执行简单的插入和删除操作。Realm Studio可以在App Store中下载安装
Realm的安装
1、手动安装
当使用手工方式安装Realm时,可以按照如下步骤进行
登录Realm官方网站或者Github,下载Realm的最新版本并解压
- 将Realm.framework从ios/static/文件夹拖曳到您Xcode项目中的文件导航器当中, 确保Copy items if needed选中然后单击Finish
- 在Xcode文件导航器中选择您的项目,然后选择您的应用目标,进入到Build Phases选项卡中。
- 在Link Binary with Libraries中单击 + 号然后添加libc++.tbd以及libz.tbd
2、使用CocoaPods安装
当使用CocoaPods方式安装Realm时,以Swift为例
- 在Podfile中,添加
pod 'RealmSwift'
- 在终端运行pod install即可安装
Xcode插件
Realm提供了一个Xcode插件,来方便的创建RLMObject类,这需要我们首先安装相关的插件
打开Realm文件夹中的plugin/RealmPlugin.xcodeproj
并进行编译,重启Xcode之后插件即可生效
当需要新建RLMObject类时,在新建类的选项中选择Realm Model Object即可
Realm的类定义说明
在Realm框架中,定义了二十个核心类、常量、枚举类型、协议等,常用的如:RLMRealm类、RLMObject类、RLMResults类等, 我们可以从Realm的官方网站上查看所有的定义以及使用说明
类型的可选和不可选对应表
Type | Non-optional | Optional |
---|---|---|
Bool | @objc dynamic var value = false | let value = RealmOptional |
Int | @objc dynamic var value = 0 | let value = RealmOptional |
Float | @objc dynamic var value: Float = 0.0 | let value = RealmOptional |
Double | @objc dynamic var value: Double = 0.0 | let value = RealmOptional |
String | @objc dynamic var value = “” | @objc dynamic var value: String? = nil |
Data | @objc dynamic var value = Data() | @objc dynamic var value: Data? = nil |
Date | @objc dynamic var value = Date() | @objc dynamic var value: Date? = nil |
Object | n/a: must be optional | @objc dynamic var value: Class? |
List | let value = List |
n/a: must be non-optional |
LinkingObjects | let value = LinkingObjects(fromType: Class.self, property: “property”) | n/a: must be non-optional |
1、RLMRealm类
一个RLMRealm类的对象可以认为是一个Realm的数据库。Realm数据库既可以存储在硬盘上,同时也可以存储在内存中 Realm是框架的核心所在,是我们构建数据库的访问点,就如同Core Data的管理对象上下文managed object context一样
1 |
|
2、RLMObject类
在Realm数据库中存储的都是RMObject对象,RLMObject类是所有可以存储在Realm数据库中的对象的根类 凡是可以存储在Realm数据库中的对象都是RLMObject类或RLMObject类的子类 要创建一个数据模型,我们只需要继承RLMObject,然后设计我们想要存储的属性即可 在RLMObject类中,我们可以添加属性,添加的属性类型可以支持如下类型:
- NSString:字符串
- NSInteger, int, long, float, double:数字型,注意没有CGFloat
- BOOL/bool:布尔型
- NSDate:日期型
- NSData:二进制字符型
- NSNumber
: 其中X必须RLMInt, RLMFloat, RLMDouble或 RLMBool类型 - RLMArray
: 其中X必须是RLMObject类的子类, 用于建模多对多关系 - RLMObject的子类,用于建模多对一关系
RLMObject类中,比较常用如下方法:
1 |
|
3、RLMResults类
当我们执行一个查询操作后,查询出满足条件的RLMObject对象会存放在一个RLMResults对象中 RLMResults类是一个数组类型的数据结构,因此在其类定义中,提供了很多与数组类似的属性和方法
相关属性
1 |
|
更多相关类及其属性和方法, 可参考官方文档
Realm的使用
Realm中一些常用的类及其类的属性和方法上面已经介绍了, 下面我们就介绍Realm的使用方法
1、创建RLMObject类
我们首先创建一个Student类,该类是RLMObject类的一个子类, 下图就是按照之前安装的Xcode插件创建的
在Student添加两个属性, RLMObject官方建议在RLMObject类中添加的属性,是不需要指定属性关键字的,完全交由Realm处理
假如设置了,这些attributes会一直生效直到RLMObject被写入realm数据库
RLM_ARRAY_TYPE宏创建了一个协议,从而允许 RLMArray
1 |
|
2、存储操作
对于RLMObject类型的对象,我们可以直接对创建的对象进行存储
第一步, 初始化对象
1 |
|
第二步就是把RLMObject对象写入Realm数据库, 同样有三种方式
1 |
|
一定要注意的是:
- 所有的必需属性都必须在对象添加到Realm前被赋值
- 如果在进程中存在多个写入操作的话,那么单个写入操作将会阻塞其余的写入操作,并且还会锁定该操作所在的当前线程
- 建议常规的最佳做法:将写入操作转移到一个独立的线程中执行
- 官方给出的建议:由于Realm采用了MVCC设计架构,读取操作并不会因为写入事务正在进行而受到影响
除非您需要立即使用多个线程来同时执行写入操作,不然您应当采用批量化的写入事务,而不是采用多次少量的写入事务 下面的代码就是把写事务放到子线程中去处理
1 |
|
3、查询操作
Realm中也提供了功能强大的数据查询能力,如果会使用SQL语言的话,上手的难度更低 在Realm的查询功能中,也可以像SQL一样使用各种条件查询关键字,查询的结果会保存在一个RLMResults类的数组中 全量查询, 通过调用allObjects方法, 得到该表中的所有数据 条件查询,设置一些查询条件,从而查询出符合条件的对象 Realm的查询条件可以使用==、<=、<、>=、>、!=、BETWEEN、CONTAINS 以及 ENDSWITH等多种操作符 全量查询
1 |
|
4、更新操作
需要修改的模型一定是被Realm所管理的模型, 而且已经和磁盘上的对象进行地址映射 对新添加的模型进行更新
1 |
|
当有主键的情况下, 使用Update方法
addOrUpdateObject
会去先查找有没有传入的Student相同的主键,如果有,就更新该条数据
这里需要注意,addOrUpdateObject这个方法不是增量更新,所有的值都必须有,如果有哪几个值是null,那么就会覆盖原来已经有的值,这样就会出现数据丢失的问题
createOrUpdateInRealm:withValue这个方法是增量更新的,后面传一个字典,使用这个方法的前提是有主键
方法会先去主键里面找有没有字典里面传入的主键的记录,如果有,就只更新字典里面的子集;如果没有,就新建一条记录
1 |
|
5、删除操作
删除的模型, 一定要求是被realm所管理的已经存在的模型 当需要在Realm中删除某些对象时,需要注意的是,该方法的执行需要在一个事务中进行
1 |
|
6、Realm数据库机制
上面用到的获取realm对象的方式都是通过defaultRealm来获取默认配置的realm对象 当我们需要创建不同的realm表格时又该如何操作呢? 下面我们来看一下
1 |
|
7、通知
Realm实例将会在每次写入事务提交后,给其他线程上的Realm实例发送通知 一般控制器如果想一直持有这个通知,就需要申请一个属性, 强引用该属性,strong持有这个通知 集合通知是异步触发的,首先它会在初始结果出现的时候触发,随后当某个写入事务改变了集合中的所有或者某个对象的时候,通知都会再次触发
1 |
|
8、数据库迁移
数据库存储方面的增删改查应该都没有什么大问题,比较蛋疼的应该就是数据迁移了 在版本迭代过程中,很可能会发生表的新增,删除,或者表结构的变化,如果新版本中不做数据迁移,用户升级到新版,很可能就直接crash了 数据迁移一直是困扰各类型数据库的一大问题, 但是对于Realm来说, 却方便很多, 这也是Realm的优点之一 新增删除表,Realm不需要做迁移 新增删除字段,Realm不需要做迁移; Realm会自行检测新增和需要移除的属性,然后自动更新硬盘上的数据库架构
1 |
|