Realm

Realm-Object-c,见:
https://realm.io/cn/docs/objc/latest/
Realm官网:
https://realm.io

使用流程

  • 导入头文件#import < Realm/Realm.h >.
  • 创建类,继承于RLMObject.
  • 在类中生成数据模型.
  • 在需要的地方创建实例,使用Realm方法调用.

数据模型

创建简单数据模型

简单地,继承RLMObject创建类,在.h中通过属性定义不同的内容.

RLMResults <0x7fe5e3d22ec0>(
[0]Data {
time = 2016-01-08 05:51:12 +0000;
title = test;
}
)

生成如上的数据结构,只需创建类如下:

// .h
#import <Realm/Realm.h> @interface Data : RLMObject
@property (nonatomic , strong) NSDate *time;
@property (nonatomic , copy) NSString *title; @end // .m
#import "Data.h" @implementation Data @end

生成主键(Primary Keys)

重写 +primaryKey 可以设置模型的主键。声明主键之后,对象将被允许查询,更新速度更加高效,并且要求每个对象保持唯一性。 一旦带有主键的对象被添加到 Realm 之后,该对象的主键将不可修改。

@interface Person : RLMObject
@property NSInteger id;
@property NSString *name;
@end @implementation Person
+ (NSString *)primaryKey {
return @"id";
}
@end

忽略属性(Ignored Properties)

重写 +ignoredProperties 可以防止 Realm 存储数据模型的某个属性。Realm 将不会干涉这些属性的常规操作,它们将由成员变量(ivar)提供支持,并且您能够轻易重写它们的 setter 和 getter。

@interface Person : RLMObject
@property NSInteger tmpID;
@property (readonly) NSString *name; // 只读属性将被自动忽略
@property NSString *firstName;
@property NSString *lastName;
@end @implementation Person
+ (NSArray *)ignoredProperties {
return @[@"tmpID"];
}
- (NSString *)name {
return [NSString stringWithFormat:@"%@ %@", self.firstName, self.lastName];
}
@end

属性默认值

重写+defaultPropertyValues可以在每次对象创建之后为其提供默认值。

@interface Book : RLMObject
@property float price;
@property NSString *title;
@end @implementation Book
+ (NSDictionary *)defaultPropertyValues {
return @{@"price" : @0, @"title": @""};
}
@end

创建嵌套数据模型

数据结构:Person具有name、birthdate、dogs,Dog具有name、owner< Person >。

RLMResults <0x7fb431f2bd60> (
[0] Person {
name = crylown;
birthdate = 2016-01-08 06:02:23 +0000;
dogs = RLMArray <0x7fb431f2fcd0> (
[0] Dog {
name = myDog;
owner = Person {
name = crylown;
birthdate = 2016-01-08 06:02:23 +0000;
dogs = <Maximum depth exceeded>;
};
},
[1] Dog {
name = yourDog;
owner = Person {
name = crylown;
birthdate = 2016-01-08 06:02:23 +0000;
dogs = <Maximum depth exceeded>;
};
}
);
}
)

生成如上的数据结构,创建数据模型代码如下:

// .h
#import <Realm/Realm.h> @class Person; // 狗狗的数据模型
@interface Dog : RLMObject
@property NSString *name;
@property Person *owner;
@end
RLM_ARRAY_TYPE(Dog) // 定义RLMArray<Dog> // 狗狗主人的数据模型
@interface Person : RLMObject
@property NSString *name;
@property NSDate *birthdate; // 通过RLMArray建立关系
@property RLMArray<Dog> *dogs; @end
RLM_ARRAY_TYPE(Person) // 定义RLMArray<Person> // .m
@implementation Dog
@end // 暂无使用 @implementation Person
@end // 暂无使用

使用Realm数据模型

创建对象

一般属性

Data *data = [[Data alloc] init];

data.time = [NSDate dateWithTimeIntervalSinceNow:0];

data.title = @"test";

等价于

 //字典
Data *data = [[Data alloc] initWithValue:@{@"time":[NSDate dateWithTimeIntervalSinceNow:0],@"title":@"test"}];

等价于

 //数组
Data *data = [[Data alloc] initWithValue:@[[NSDate dateWithTimeIntervalSinceNow:0],@"test"]];

嵌套属性

Person *me = [[Person alloc] init];

Dog *myDog = [[Dog alloc] init];
myDog.name = @"myDog";
myDog.owner = me; Dog *yourDog = [[Dog alloc] init];
yourDog.name = @"yourDog";
yourDog.owner = me; me.name = @"crylown";
me.birthdate = [NSDate dateWithTimeIntervalSinceNow:1]; // 将dog添加到 <RLMArray>dogs属性中
[me.dogs addObject:myDog];
[me.dogs addObject:yourDog];

等价于

Dog *myDog = [[Dog alloc] init];
myDog.name = @"myDog"; Dog *yourDog = [[Dog alloc] init];
yourDog.name = @"yourDog"; Person *me = [[Person alloc] initWithValue:@[@"crylown",[NSDate dateWithTimeIntervalSinceNow:1],@[myDog,yourDog]]]; yourDog.owner = me;
myDog.owner = me;

等价于

// 多重嵌套
// dog.owner无法在这里设置
Person *me = [[Person alloc] initWithValue:@[@"crylown",[NSDate dateWithTimeIntervalSinceNow:1],@[@[@"myDog"],@[@"yourDog"]]]];

使用Realm进行数据管理

在数据管理的过程中,常用的方法有:

 RLMRealm *realm = [RLMRealm defaultRealm];

// 开放RLMRealm事务
[realm beginWriteTransaction]; // 在开放开放/提交事务之间进行数据处理 // 提交事务
[realm commitWriteTransaction];

等价于

[realm transactionWithBlock:^{

 // 进行数据处理

}];

添加数据

 RLMRealm *realm = [RLMRealm defaultRealm];

//    开放RLMRealm事务
[realm beginWriteTransaction]; // 添加到数据库 me为RLMObject
[realm addObject:me]; // 提交事务
[realm commitWriteTransaction];

查询数据

数据库查询

// 查询默认的 Realm 数据库
RLMResults *dogs = [Dog allObjects]; // 从默认的 Realm 数据库中,检索所有狗狗

如果有需要,也可以查询指定的数据库

// 查询指定的 Realm 数据库
RLMRealm *petsRealm = [RLMRealm realmWithPath:@"pets.realm"]; // 获得一个指定的 Realm 数据库
RLMResults *otherDogs = [Dog allObjectsInRealm:petsRealm]; // 从该 Realm 数据库中,检索所有狗狗

条件查询
1.使用断言字符串查询:

RLMResults *tanDogs = [Dog objectsWhere:@"color = '棕黄色' AND name BEGINSWITH '大'"];

2.// 使用 NSPredicate 查询

NSPredicate *pred = [NSPredicate predicateWithFormat:@"color = %@ AND name BEGINSWITH %@",
@"棕黄色", @"大"];
RLMResults *tanDogs = [Dog objectsWithPredicate:pred];

3.链式查询

如果我们想获得获得棕黄色狗狗的查询结果,并且在这个查询结果的基础上再获得名字以“大”开头的棕黄色狗狗。

RLMResults *tanDogs = [Dog objectsWhere:@"color = '棕黄色'"];
RLMResults *tanDogsWithBNames = [tanDogs objectsWhere:@"name BEGINSWITH '大'"];

修改数据

内容直接更新

// author为数据库内RLMObject
[realm beginWriteTransaction];
author.name = @"托马斯·品钦";
[realm commitWriteTransaction];

根据主键更新
如果您的数据模型中设置了主键的话,那么您可以使用+[RLMObject createOrUpdateInRealm:withValue:]来更新对象,或者当对象不存在时插入新的对象。

// 创建一个带有主键的“书籍”对象,作为事先存储的书籍
Book *cheeseBook = [[Book alloc] init];
cheeseBook.title = @"奶酪食谱";
cheeseBook.price = @9000;
cheeseBook.id = @1; // 通过 id = 1 更新该书籍
[realm beginWriteTransaction];
[Book createOrUpdateInRealm:realm withValue:cheeseBook];
[realm commitWriteTransaction];

键值编码
RLMObject、RLMResult 以及 RLMArray 都遵守键值编码(Key-Value Coding)(KVC)机制。

RLMResults *persons = [Person allObjects];

[[RLMRealm defaultRealm] transactionWithBlock:^{
[[persons firstObject] setValue:@YES forKeyPath:@"isFirst"];
// 将每个人的 planet 属性设置为“地球”
[persons setValue:@"地球" forKeyPath:@"planet"];
}];

删除数据

删除某个在Realm数据库中的数据。

Book *cheeseBook = ... // 存储在 Realm 中的 Book 对象

// 在事务中删除一个对象
[realm beginWriteTransaction];
[realm deleteObject:cheeseBook];
[realm commitWriteTransaction];

删除数据库中的所有数据。

// 从 Realm 中删除所有数据
[realm beginWriteTransaction];
[realm deleteAllObjects];
[realm commitWriteTransaction];

数据排序

RLMResults 允许您指定一个排序标准,从而可以根据一个或多个属性进行排序。比如说,下列代码将上面例子中返回的狗狗根据名字升序进行排序:

// 排序名字以“大”开头的棕黄色狗狗
RLMResults *sortedDogs = [[Dog objectsWhere:@"color = '棕黄色' AND name BEGINSWITH '大'"]
sortedResultsUsingProperty:@"name" ascending:YES];

数据库配置

一般地,我们使用的为默认的Realm数据库,即调用[RLMRealm defaultRealm]来初始化以及访问我们的realm变量。这个方法将会返回一个 RLMRealm对象,并指向您应用的 Documents (iOS) 或者 Application Support (OS X)文件夹下的一个名为“default.realm”的文件。

许多 Realm API 中的方法都支持两种默认的数据库访问方式,一种是RLMRealm实例,另一种是访问默认 Realm 数据库的便捷版本。例如 [RLMObject allObjects] 等同于 [RLMObject allObjectsInRealm:[RLMRealm defaultRealm]]。

Realm配置

通过RLMRealmConfiguration您可以配置诸如 Realm 文件在何处存储之类的信息。
配置同时也可以在每次您需要使用 Realm 实例的时候传递给[RLMRealm realmWithConfiguration:config error:&err],或者您也可以通过 [RLMRealmConfiguration setDefaultConfiguration:config] 来为默认的 Realm 数据库进行配置。
比如说,假设有这样一个应用,用户必须登录到您的网站后台才能够使用,然后您希望这个应用支持快速帐号切换功能。 您可以为每个帐号创建一个特有的 Realm 文件,通过对默认配置进行更改,就可以直接使用默认的 Realm 数据库来直接访问了,如下所示:

+ (void)setDefaultRealmForUser:(NSString *)username {
RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration]; // 使用默认的目录,但是使用用户名来替换默认的文件名
config.path = [[[config.path stringByDeletingLastPathComponent]
stringByAppendingPathComponent:username]
stringByAppendingPathExtension:@"realm"]; // 将这个配置应用到默认的 Realm 数据库当中
[RLMRealmConfiguration setDefaultConfiguration:config];
}

其他的Realm数据库

有的时候,在不同位置存储多个 Realm 数据库是十分有用的。 例如,如果您需要将您应用的某些数据打包到一个 Realm 文件中,作为主要 Realm 数据库的扩展。 您可以像以下代码这样做:

RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];

// 获取需要打包文件的路径
config.path = [[NSBundle mainBundle] pathForResource:@"MyBundledData" ofType:@"realm"];
// 以只读模式打开文件,因为应用数据包并不可写
config.readOnly = YES; // 通过配置打开 Realm 数据库
RLMRealm *realm = [RLMRealm realmWithConfiguration:config]; // 从打包的 Realm 数据库中读取某些数据
RLMResults<Dog *> *dogs = [Dog objectsInRealm:realm where:@"age > 5"];

请注意,使用自定义路径来初始化 Realm 数据库需要拥有路径所在位置的写入权限。 通常存储可写 Realm 文件的地方是位于 iOS 上的“Documents”文件夹以及位于 OS X 上的“Application Support”文件夹。 具体情况,请遵循苹果的 iOS 数据存储指南, 它推荐将文件存储在<Application_Home>/Library/Caches目录下

错误处理

在数据的处理中可能会出现失败的情况,在查看错误的时候,有相关方法可以使用:
提交事务失败

[realm commitWriteTransaction:(NSError * _Nullable __autoreleasing * _Nullable)]

也可以使用

[realm transactionWithBlock:^{

} error:(NSError * _Nullable __autoreleasing * _Nullable)]

配置数据库失败

RLMRealm *realm = [RLMRealm realmWithConfiguration:config error:&error];

要处理在指定线程中初次 Realm 数据库导致的错误, 给 error 参数提供一个 NSError 指针。

数据迁移

当您使用任意一个数据库时,您随时都可能打算修改您的数据模型。通过设置 RLMRealmConfiguration.schemaVersion 以及RLMRealmConfiguration.migrationBlock 可以定义一个迁移操作以及与之关联的架构版本。 迁移闭包将会提供提供相应的逻辑操作,以让数据模型从之前的架构转换到新的架构中来。 每当通过配置创建完一个 RLMRealm 之后,迁移闭包将会在迁移需要的时候,将给定的架构版本应用到更新 RLMRealm 操作中。
如下所示是最简单的数据迁移的必需流程:

// 在 [AppDelegate didFinishLaunchingWithOptions:] 中进行配置

RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
// 设置新的架构版本。这个版本号必须高于之前所用的版本号(如果您之前从未设置过架构版本,那么这个版本号设置为 0)
config.schemaVersion = 1; // 设置闭包,这个闭包将会在打开低于上面所设置版本号的 Realm 数据库的时候被自动调用
config.migrationBlock = ^(RLMMigration *migration, uint64_t oldSchemaVersion) {
// 目前我们还未进行数据迁移,因此 oldSchemaVersion == 0
if (oldSchemaVersion < 1) {
// 什么都不要做!Realm 会自行检测新增和需要移除的属性,然后自动更新硬盘上的数据库架构
}
}; // 告诉 Realm 为默认的 Realm 数据库使用这个新的配置对象
[RLMRealmConfiguration setDefaultConfiguration:config]; // 现在我们已经告诉了 Realm 如何处理架构的变化,打开文件之后将会自动执行迁移
[RLMRealm defaultRealm];

iOS开发-Realm数据库的更多相关文章

  1. iOS中Realm数据库的基本用法

      原文  http://git.devzeng.com/blog/simple-usage-of-realm-in-ios.html 主题 RealmiOS开发 Realm是由 Y Combinat ...

  2. IOS开发——使用数据库

    IOS开发——使用FMDB数据库 简介 需求作用: 如果需要保存大量的结构较为复杂的数据的时候,使用数据库,例如交规考试项目 1.数据库的基本介绍 数据库(DB)是一种数据模型组织起来并存放存储管理的 ...

  3. IOS开发-封装数据库sqlite3之为何选择FMDB

    为什么使用第三方轻量级框架FMDB? FMDB是用于进行数据存储的第三方的框架,它与SQLite与Core Data相比较,存在很多优势. FMDB是面向对象的,它以OC的方式封装了SQLite的C语 ...

  4. iOS开发数据库篇—SQLite简单介绍

    iOS开发数据库篇—SQLite简单介绍 一.离线缓存 在项目开发中,通常都需要对数据进行离线缓存的处理,如新闻数据的离线缓存等. 说明:离线缓存一般都是把数据保存到项目的沙盒中.有以下几种方式 (1 ...

  5. iOS开发数据库篇—SQL

    iOS开发数据库篇—SQL 一.SQL语句 如果要在程序运行过程中操作数据库中的数据,那得先学会使用SQL语句 1.什么是SQL SQL(structured query language):结构化查 ...

  6. iOS开发数据库篇—SQL代码应用示例

    iOS开发数据库篇—SQL代码应用示例 一.使用代码的方式批量添加(导入)数据到数据库中 1.执行SQL语句在数据库中添加一条信息 插入一条数据的sql语句: 点击run执行语句之后,刷新数据 2.在 ...

  7. iOS开发数据库篇—SQLite的应用

    iOS开发数据库篇—SQLite的应用 一.简单说明 在iOS中使用SQLite3,首先要添加库文件libsqlite3.dylib和导入主头文件. 导入头文件,可以使用库中的函数(是纯C语言的) 二 ...

  8. IOS开发数据库篇—SQLite模糊查询

    IOS开发数据库篇—SQLite模糊查询 一.示例 说明:本文简单示例了SQLite的模糊查询 1.新建一个继承自NSObject的模型 该类中的代码: // // YYPerson.h // 03- ...

  9. iOS开发数据库篇—SQLite常用的函数

    iOS开发数据库篇—SQLite常用的函数 一.简单说明 1.打开数据库 int sqlite3_open( const char *filename,   // 数据库的文件路径 sqlite3 * ...

随机推荐

  1. Jackson 框架JSON、XML、List、Map直接相互转换

    博客分类: json   参考:http://www.cnblogs.com/hoojo/archive/2011/04/22/2024628.html 在其基础上做了稍微调整 详情见附件 jacks ...

  2. logstash在Windows2008简单配置实例

    Windows2008 安装java1.8,配置系统环境变量: 官方下载并安装略...然后配置 logstash的配置文件 注意PATH路径名称不支持中文 input { file { type =& ...

  3. LeetCode—— Partition Equal Subset Sum

    Question Given a non-empty array containing only positive integers, find if the array can be partiti ...

  4. codeforces 578c - weekness and poorness - 三分

    2017-08-27 17:24:07 writer:pprp 题意简述: • Codeforces 578C Weakness and poorness• 给定一个序列A• 一个区间的poornes ...

  5. Linux 安装rabbitmq 遇到的一些问题

    Linux下防火墙开启相关端口及查看已开启端口 https://www.cnblogs.com/pizitai/p/6518987.htmlhttps://www.cnblogs.com/blog-y ...

  6. 机器学习笔记—K-均值聚类

    在聚类问题中,给定训练集 {x(1),...,x(m)},要把数据分成内聚的“簇”.这里 x(i)∈R,没有 y(i).所以,这是一个无监督学习问题. k-均值聚类算法如下: 1.随机初始化簇中心 μ ...

  7. bash-文件表达式

    一点例子: #!/bin/bash # test-file: Evaluate the status of a file FILE=~/.bashrc if [ -e "$FILE" ...

  8. linux ps 命令参数详解

    -a 显示所有终端机下执行的进程,除了阶段作业领导者之外. a 显示现行终端机下的所有进程,包括其他用户的进程. -A 显示所有进程. -c 显示CLS和PRI栏位. c 列出进程时,显示每个进程真正 ...

  9. 使用lock锁或Monitor.Enter的目的

    锁定的目的:由于多个线程 并行/并发 处理同一个“数据对象”(比如:在其它线程的某个地方发生了Clear.Add.Remove.Change等操作),导致“数据对象”不断变化,没法用了,所以,为了保证 ...

  10. 【Error】local variable 'xxx' referenced before assignment

    此种错误涉及到变量的作用域,即全局变量和局部变量的操作. 总结如下: 内部函数,不修改全局变量可以访问全局变量 内部函数,修改同名全局变量,则python会认为它是一个局部变量 在内部函数修改同名全局 ...