今天我们一起来学习一下Realm 数据库。
先介绍一下Realm 数据库,Realm 是一个移动数据库,可运行于手机、平板和可穿戴设备之上。可以让你的应用更快速,带来难以想象的体验。其目标是为了代替 CoreData 和 SQLite 数据库。目前支持 iOS/OS X/Android 平台,提供 Swift/Objective-C/Java 语言的 API ,目前 Realm数据库是代码闭源。
首先先学习一下Objective-C语言的API。
硬件需求:
1 使用 Realm 构建应用的基本要求:iOS >= 7, OS X >= 10.9 并且支持 WatchKit
2 需要使用 Xcode 6.4 或者以后的版本;
3在苹果商店下载一个Realm Browser 的软件;
由于本人喜欢用CocoaPods ,所以直接用CocoaPods.
1 安装CococaPods 0.37.1或者更高版本;
2 在您的Podfile中,添加pod 'Realm'到您的 app 目标中,添加pod 'Realm/Headers'到您的测试目标中;(可能网速卡,多试几次就好了,最好开翻墙)
3 在终端用 pod install --verbose --no-repo-update 或者 pod update --verbose --no-repo-update 进行安装 Realm 第三方库
4 采用 CocoaPods 生成的.xcworkspace来运行工程!
现在开始按照上面的方法简历一个新的工程 把Realm 第三方库 通过 CocoaPods 安装后 打开工程。
1 创建模型
您可以使用RLMArray和RLMObject的子类来建立诸如一对多、一对一之类的关系模型
在 Xcode 7 以及之后的版本中,RLMArray支持编译时的 Objective-C 泛型(generics)。下面是不同属性定义方法的意义以及用途:
RLMArray: 属性类型。
: 属性的特别化(generic specialization),这可以阻止在编译时使用错误对象类型的数组。
: 此RLMArray遵守的协议,可以让 Realm 知晓如何在运行时确定数据模型的架构。
首先我们创建一个Person继承RLMObject的类 创建 Dog类和Person类之间的关系,
RLMObject能够借助RLMObject以及RLMArray属性来和另一个RLMObject建立联系。RLMArray表面上和NSArray非常类似,在RLMArray中的对象能够使用索引下标(indexed subscripting)来进行访问。 和 NSArray 不同,RLMArray的类型是固定的,其中只能存放简单的RLMObject子类类型。
对一(To-One)关系
对于多对一(many-to-one)或者一对一(one-to-one)关系来说,只需要声明一个RLMObject子类类型的属性即可
对多(To-Many)关系
通过 类型的属性您可以定义一个对多关系。RLMArray中可以包含简单类型的RLMObject,表面上和NSMutableArray非常类似。
如果打算给我们的 Person 数据模型添加一个“dogs”属性,以便能够和多个“dogs”建立关系,也就是表明一个 Person 可以有多个 Dog,那么我们首先需要定义一个RLMArray类型。通过对应数据模型接口文件下的宏命令即可完成:
RLM_ARRAY_TYPE(Dog)//定义RLMArray
以上两种情况也可以通过属性进行访问和赋值
Person*jim=[[Personalloc]init];
Dog*rex=[[Dogalloc]init];
rex.owner=jim;
反向关系(Inverse Relationship)
链接是单向性的。因此,对于对多属性Person.dogs来说,其会链接到一个Dog实例,对于对一属性Dog.owner来说也会链接到Person实例。这些链接相互之间是互相独立的。为Person实例的dogs属性添加一个新的Dog,并不会自动将狗狗的owner属性设置为该Person。由于手动同步关系对会很容易出错,并且还会让内容变得复杂、冗余,Realm 提供了一个 API 来取得反向链接(backlink),如下所述。
通过反向关系(也被称为反向链接(backlink)),您可以通过一个特定的属性获取和给定对象有关系的所有对象。比如说,对Dog的实例调用-linkingObjectsOfClass:forProperty:会返回对应的与被调用实例所指定属性的类有关系的所有对象。通过在Dog中定义一个只读(计算)属性owners可以简化这个操作:
可选属性(Optional Properties)
通常情况下,NSString、NSData以及NSDate属性可以设置为nil。
如果你不需要实现此功能,你可以重写您的RLMObject子类的+requiredProperties方法。
比如对于以下的模型定义来说,如果尝试给 name 属性设置为nil将会抛出一个异常,但是将 birthday 属性设置为nil却是允许的:
存储可空数字目前已经可以通过NSNumber属性完成。 由于 Realm 对不同类型的数字采取了不同的存储格式,因此设置可空的数字属性必须是RLMInt、RLMFloat、RLMDouble或者RLMBool其中一个类型。
属性特性(attributes)
注意由于 Realm 在自己的引擎内部有很好的语义解释系统,所以Objective-C的许多属性特性将被忽略,如nonatomic,atomic,strong,copy和weak等。 因此为了避免误解,我们推荐您在编写数据模型的时候不要使用任何的属性特性。 当然,如果您已经设置了,在有RLMObject对象被写入realm数据库前,这些特性会一直生效。 无论是否有RLMObject对象存在于 realm 中,您为getter和setter自定义的名字都能正常工作。
索引属性(Indexed Properties)
重写+indexedProperties方法可以为数据模型中需要添加索引的属性建立索引:
属性默认值
重写+defaultPropertyValues可以在每次对象创建之后为其提供默认值。
主键(Primary Keys)
重写+primaryKey可以设置模型的主键。声明主键之后,对象将被允许查询,更新速度更加高效,并且要求每个对象保持唯一性。 一旦带有主键的对象被添加到 Realm 之后,该对象的主键将不可修改。
忽略属性(Ignored Properties)
重写+ignoredProperties可以防止 Realm 存储数据模型的某个属性。Realm 将不会干涉这些属性的常规操作,它们将由成员变量(ivar)提供支持,并且您能够轻易重写它们的 setter 和 getter
前面已经介绍完基本类型的使用 ,下面来介绍存储数据
最重要的一点:
对对象的所有更改(添加,修改和删除)都必须通过写入事务(transaction)完成。
1 创建对象
创建一个Book类 继承 RLMObject 有两个属性 分别是书名 和 价格
我们使用这个类 在ViewController 里面的 viewDidLoad 方法里面 写下面的代码
除此之外还可以嵌套对象初始化
我们来添加数据 接着在上面的代码写下
打印一下模拟器Documents 路径
里面有个default.realm文件
我们用 realm browser 打开 default.realm 文件
我们已经把数据 添加成功!
二 更新数据
我们把刚才的添加数据库的代码注释掉,在新写一个函数 searchResult 把书名为OC 的价格从50 改到200
1 内容直接更新
您可以在写入事务中通过设置某个对象的属性从而完成对象的更新操作。
来看一下数据库
值已经改变了 50 到200
2 通过主键更新
如果您的数据模型中设置了主键的话,那么您可以使用+[RLMObject createOrUpdateInRealm:withValue:]来更新对象,或者当对象不存在时插入新的对象。
如果主键 id 的书籍在数据库中不存在,那么这个操作将会创建一个新的书籍。
您同时通过传递您想要更新值的集合,从而更新带有主键的某个对象的部分值,比如说如下所
3 键值编码
RLMObject、RLMResult 以及 RLMArray 都遵守键值编码(Key-Value Coding)(KVC)机制。 当您在运行时才能决定哪个属性需要更新的时候,这个方法是最有用的。
将 KVC 应用在集合当中是大量更新对象的极佳方式,这样就可以不用经常遍历集合,为每个项目创建一个访问器了。
三 删除数据
通过在写入事务中将要删除的对象传递给-[RLMRealm deleteObject:]方法,即可完成删除操作。
四 查询
条件查询(Filtering)
如果您熟悉NSPredicate的话,那么您就能很容易掌握其在 Realm 中的查询方法。RLMObjects、RLMRealm、RLMArray以及RLMResults都提供了方法,允许您通过简单地传递一个 NSPredicate 实例、断言字符串或者断言格式化字符串来完成查询这顶RLMObject实例的操作,正如您在 NSArray 中执行查询的哪样。
比如说,下面的例子就展示了如何通过从默认的 Realm 数据库中调用[RLMObject objectsWhere:]方法来检索所有棕黄色,并且以“大”开头命名的狗狗的:
// 使用断言字符串查询RLMResults*tanDogs=[DogobjectsWhere:@"color = '棕黄色' AND name BEGINSWITH '大'"];
// 使用 NSPredicate 查询NSPredicate*pred=[NSPredicatepredicateWithFormat:@"color = %@ AND name BEGINSWITH %@",@"棕黄色",@"大"];
tanDogs=[DogobjectsWithPredicate:pred];
可以学习一下 查看苹果的断言编程指南来获取更多关于断言查询和NSPredicate Cheatsheet的使用信息。
要了解关于断言的更多详情,请查看[RLMObject objectsWhere:]的详细信息。
五 排序
RLMResults允许您指定一个排序标准,从而可以根据一个或多个属性进行排序。比如说,下列代码将上面例子中返回的狗狗根据名字升序进行排序:
// 排序名字以“大”开头的棕黄色狗狗
RLMResults*sortedDogs=[[DogobjectsWhere:@"color = '棕黄色' AND name BEGINSWITH '大'"]sortedResultsUsingProperty:@"name"ascending:YES];
关于排序的更多信息,请查看[RLMResults sortedResultsUsingProperty:ascending:]的详细信息。
这篇文章只是初级的使用方法 如果了解更多请移步 https://realm.io/cn/docs/objc/latest/