Realm是由 Y Combinator 公司孵化的一款支持运行在手机、平板和可穿戴设备上的嵌入式数据库(旨在取代CoreData和Sqlite)。Realm并不是对Core Data的简单封装,相反地,Realm并不是基于Core Data,也不是基于SQLite所构建的。它拥有自己的数据库存储引擎,可以高效且快速地完成数据库的构建操作。

Realm可以轻松地移植到项目当中,并且绝大部分常用的功能(比如说插入、查询等等)都可以用一行简单的代码轻松完成!目前支持Objective-C、Swift和Java三种语言,也就是说能在iOS、Android和Mac上面跨平台使用。

综上,Realm主要有以下几个优点:

  • Easy to Use(简单易用):Core Data和SQLite冗余、繁杂的知识和代码足以吓退绝大多数刚入门的开发者,而换用Realm,则可以极大地减少学习代价和学习时间,让应用及早用上数据存储功能。

  • Cross-Platform(跨平台):现在绝大多数的应用开发并不仅仅只在iOS平台上进行开发,还要兼顾到Android平台的开发。为两个平台设计不同的数据库是愚蠢的,而使用Realm数据库,iOS和Android无需考虑内部数据的架构,调用Realm提供的API就可以完成数据的交换,实现“一个数据库,两个平台无缝衔接”。

  • Fast(高效):Realm相比使用CoreData和原生的SQLite来说速度更快更加高效,而且代码量更少。

快速集成Realm

1、下载最新的 Realm 更新包,解压zip文件

2、将 ios/static 目录下面的 Realm.framework 文件拖到项目里面(确保Copy items if needed选中)

3、在 target -> Build Phases -> Link Binary with Libraries 中添加 libc++.dylib

说明:

(1)对于使用Swift的童鞋,请讲Swift/RLMSupport.swift文件拖到项目中(确保Copy items if needed选中)

(2)推荐使用Cocoapods进行安装,在Podfile中添加 pod 'Realm' 即可

(3)也可以自行到Github上面下载代码进行编译,此处不作过多的介绍

运行环境:

(1)支持 >= iOS7.0, >= OS X 10.9, 及WatchKit

(2)推荐使用Xcode 5以上的IDE,支持Swift

辅助工具和插件的安装

1、Realm Browser

Realm官方非常贴心的向开发者提供了一个用于查看喝编辑Realm数据的工具 Realm Browser .

在上面下载的更新包的 browser/ 下面有个Realm Browser拖到Application文件夹或者是直接打开都行。另外可以使用菜单的 tool -> generate demo datebase ,生成测试数据用于测试Realm数据库的使用

2、Xcode Plugin(Xcode8之后好像苹果大大不再支持Xcode插件,如果硬是要使用插件,还是有办法的,请自行谷歌)

在Realm中使用到最多的是Realm Model(继承自RLMObject的类,后面有介绍)。官方提供了一个Xcode的插件让我们在创建模型变得非常轻松

安装使用:

(1)最简单的安装方式是通过Alcatraz,搜索 RealmPlugin 直接安装

(2)或者是打开zip文件夹下面的 plugin/RealmPlguin.xcodeproj ,build一下就安装好了

安装完后重启Xcode生效,在创建model的时候选择New File(或⌘N),选择Realm按照要求输入model的名字就OK啦。

Realm的使用

1、构建数据库

Realm提供了三种方式创建数据库,一种是存储在默认路径下的数据库,一种是我们可以自己指定数据库文件的存储路径和只读属性,另外还可以使用内存数据库。

(1)默认Realm数据库

RLMRealm *realm = [RLMRealm defaultRealm];

可以通过: [RLMRealm defaultRealmPath] 查看默认存储的路径。

(2)自定义Realm数据库

NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *dbPath = [docPath stringByAppendingPathComponent:@"db/db.realm"];
RLMRealm *realm = [RLMRealm realmWithPath:dbPath];

或者是

NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *dbPath = [docPath stringByAppendingPathComponent:@"db/db.realm"];
RLMRealm *realm = [RLMRealm realmWithPath:dbPath readOnly:YES error:nil];

其中readOnly表示创建的数据库是只读数据库。

(3)内存数据库

正常的Realm数据库是存储在硬盘上的, 但你也可以通过使用 + (instancetype)inMemoryRealmWithIdentifier:(NSString *)identifier; 来创建一个内存数据库。

RLMRealm *realm = [RLMRealm inMemoryRealmWithIdentifier:@"test"];

注意:内存数据库在每次程序退出时不会保存数据。如果某个内存Realm实例没有被引用,所有的数据在实例对象释放的适合也会被释放。建议你在app中用强引用来钳制所有新建的内存Realm数据库实例。

2、数据模型

Realm的数据模型是用传统的Objective-C接口(interface)和属性(@property)定义的。 只要定义 RLMObject 的一个子类或者一个现成的模型类,你就能轻松创建一个Realm的数据模型对象。Realm模型对象和其他的Objective-c的功能很相似–你可以给它们添加你自己的方法和protocol然后和其他的对象一样使用。 唯一的限制就是从它们被创建开始,只能在一个进程中被使用。

如果已经安装了Realm Xcode插件,在 New File 对话框中会有一个很漂亮的样板,你可以用它来创建interface和implementation文件。

用一个对象来表示一篇文章(Articl),创建的数据模型如下:

  • Article.h
@interface Article : RLMObject

@property NSString *num;//序号
@property NSString *title;//标题
@property NSString *link;//链接地址
@property NSString *author;//作者
@property NSString *tag;//标签分类
@property NSInteger weight;//权重 @end RLM_ARRAY_TYPE(Article)
  • Article.m
@implementation Article

//主键
+ (NSString *)primaryKey {
return @"num";
} //需要添加索引的属性
+ (NSArray *)indexedProperties {
return @[@"title"];
} //默认属性值
+ (NSDictionary *)defaultPropertyValues {
return @{@"author":@"zengjing"};
} //忽略的字段
+ (NSArray *)ignoredProperties {
return @[@"weight"];
} @end

说明:

(1)Realm支持以下的属性(property)种类:BOOL, bool, int, NSInteger, long, float, double, CGFloat, NSString, NSDate 和 NSData。

(2)你可以使用 RLMArray<Object> 和 RLMObject 来模拟对一或对多的关系(Realm也支持RLMObject继承)

(3)Realm忽略了Objective-C的property attributes(如nonatomic, atomic, strong, copy, weak 等等)。 所以,推荐在创建模型的时候不要使用任何的property attributes。但是,假如你设置了,这些attributes会一直生效直到RLMObject被写入realm数据库。

(4)定义了 RLM_ARRAY_TYPE(Article) 这个宏表示支持 RLMArray<Article> 该属性

(5)另外Realm提供了以下几个方法供对属性进行自定义:

1) + (NSArray *)indexedProperties; : 可以被重写来来提供特定属性(property)的属性值(attrbutes)例如某个属性值要添加索引。

2) + (NSDictionary *)defaultPropertyValues; : 为新建的对象属性提供默认值。

3) + (NSString *)primaryKey; : 可以被重写来设置模型的主键。定义主键可以提高效率并且确保唯一性。

4) + (NSArray *)ignoredProperties; :可以被重写来防止Realm存储模型属性。

3、数据增删改查

(1)存储数据

创建数据模型对象:

Article *article = [[Article alloc] init];
article.num = @"1";
article.title = @"iOS开发中集成Reveal";
article.link = @"http://blog.devzeng.com/blog/ios-reveal-integrating.html";
article.tag = @"iOS";

存储数据:

RLMRealm *realm = [RLMRealm defaultRealm];
[realm beginWriteTransaction];
[realm addObject:article];
[realm commitWriteTransaction];

(2)删除数据

1)删除指定的数据:

- (void)deleteObject:(RLMObject *)object;

2)删除一组数据:

- (void)deleteObjects:(id)array;

3)删除全部的数据:

- (void)deleteAllObjects;

(3)修改数据

修改数据如果该条数据不存在则会新建一条数据。

1)针对单个数据进行的修改或新增:

- (void)addOrUpdateObject:(RLMObject *)object;

2)针对一组数据的修改或新增:

- (void)addOrUpdateObjectsFromArray:(id)array;

说明:对于增加、删除、修改必须要在事务中进行操作。

(5)查询数据

1)查询全部数据

RLMResults *results = [Article allObjects];

或指定Realm数据库:

NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *realmPath = [path stringByAppendingPathComponent:@"devzeng.realm"];
RLMRealm *realm = [RLMRealm realmWithPath:realmPath];
RLMResults *results = [Article allObjectsInRealm:realm];

2)条件查询

假设要查询所有分组是iOS和作者是zengjing的文章:

RLMResults *results = [Article objectsWhere:@"tag = 'iOS' AND author = 'zengjing'"];

也可以使用谓词查询:

NSPredicate *pred = [NSPredicate predicateWithFormat:@"tag = '%@' AND author = '%@'", @"iOS", @"zengjing"];
RLMResults *results = [Article objectsWithPredicate:pred];

3)条件排序

假设要查询所有分组是iOS和作者是zengjing的文章,然后筛选出来的结果按照num字段进行递增排序:

RLMResults *results = [[Article objectsWhere:@"tag = 'iOS' AND author = 'zengjing'"] sortedResultsUsingProperty:@"num" ascending:YES];

4)链式查询(结果过滤)

假设要查询所有所属分组是iOS的文章,然后从中筛选出作者是zengjing的数据:

RLMResults *results1 = [Article objectsWhere:@"tag = 'iOS'"];
RLMResults *results2 = [results1 objectsWhere:@"author = 'zengjing'"];

4、通知

每当一次写事务完成Realm实例都会向其他线程上的实例发出通知,可以通过注册一个block来响应通知:

self.token = [realm addNotificationBlock:^(NSString *note, RLMRealm * realm) {
[_listTableView reloadData];
}];

只要有任何的引用指向这个返回的notification token,它就会保持激活状态。在这个注册更新的类里,你需要有一个强引用来钳制这个token, 因为一旦notification token被释放,通知也会自动解除注册。

@property (nonatomic, strong) RLMNotificationToken *token;

另外可以使用下面的方式解除通知:

[realm removeNotification:self.token];

5、数据库版本迁移

当你和数据库打交道的时候,时不时的你需要改变数据模型(model),但因为Realm中得数据模型被定义为标准的Objective-C interfaces,要改变模型,就像改变其他Objective-C interface一样轻而易举。举个例子,假设有个数据模型 Person :

在v1.0中数据模型如下:

// v1.0
@interface Person : RLMObject
@property NSString *firstName;
@property NSString *lastName;
@property int age;
@end

升级到v2.0之后将firstName和lastName字段合并为一个字段fullName

// v2.0
@interface Person : RLMObject
@property NSString *fullName; // new property
@property int age;
@end

迁移的逻辑可以为:

[RLMRealm setSchemaVersion:2.0 forRealmAtPath:[RLMRealm defaultRealmPath]
withMigrationBlock:^(RLMMigration *migration,
NSUInteger oldSchemaVersion) {
[migration enumerateObjects:Person.className
block:^(RLMObject *oldObject, RLMObject *newObject) {
if (oldSchemaVersion < 2.0) {
newObject[@"fullName"] = [NSString stringWithFormat:@"%@ %@", oldObject[@"firstName"], oldObject[@"lastName"]];
}
}];
}];

当版本升级到3.0时,添加新的属性email

// v3.0
@interface Person : RLMObject
@property NSString *fullName;
@property NSString *email; // new property
@property int age;
@end

迁移的逻辑可以为:

[RLMRealm setSchemaVersion:2.0 forRealmAtPath:[RLMRealm defaultRealmPath]
withMigrationBlock:^(RLMMigration *migration,
NSUInteger oldSchemaVersion) {
[migration enumerateObjects:Person.className
block:^(RLMObject *oldObject, RLMObject *newObject) {
//处理v2.0的更新
if (oldSchemaVersion < 2.0) {
newObject[@"fullName"] = [NSString stringWithFormat:@"%@ %@", oldObject[@"firstName"], oldObject[@"lastName"]];
}
//处理v3.0的更新
if(oldSchemaVersion < 3.0) {
newObject[@"email"] = @"";
}
}];
}];

说明(摘自官方的FAQ)

1、realm的支持库有多大?

一旦你的app编译完成,realm的支持库应该只有1MB左右。我们发布的那个可能有点大(iOS ~37MB, OSX ~2.4MB), 那是因为它们还包含了对其他构架的支持(ARM,ARM64,模拟器的是X86)和一些编译符号。 这些都会在你编译app的时候被Xcode自动清理掉。

2、我应该在正式产品中使用realm吗?

自2012年起,realm就已经开始被用于正式的商业产品中了。正如你预期,我们的objective-c & Swift API 会随着社区的反馈不断的完善和进化。 所以,你也应该期待realm带给你更多的新特性和版本修复。

3、我要付realm的使用费用吗?

不要, Realm的彻底免费的, 哪怕你用于商业软件。

参考资料

1、 《Realm Document》

2、 《Realm数据库基础教程》

iOS中Realm数据库的基本用法的更多相关文章

  1. QF——iOS中的数据库操作:SQLite数据库,第三方封装库FMDB,CoreData

    SQLite数据库: SQLite是轻量级的数据库,适合应用在移动设备和小型设备上,它的优点是轻量,可移植性强.但它的缺点是它的API是用C写的,不是面向对象的.整体来说,操作起来比较麻烦.所以,一般 ...

  2. iOS中的数据库应用

    iOS中的数据库应用 SLQLite简介 什么是SQLite SQLite是一款轻型的嵌入式数据库 它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了 它的处理速度比Mysql.Post ...

  3. iOS中 Realm错误总结整理 韩俊强的博客

    每日更新关注:http://weibo.com/hanjunqiang  新浪微博! 一.错误信息:Attempting to modify object outside of a write tra ...

  4. iOS中 Realm的学习与使用 韩俊强的博客

    每日更新关注:http://weibo.com/hanjunqiang  新浪微博! 有问题或技术交流可以咨询!欢迎加入! 这篇直接搬了一份官方文档过来看的 由于之前没用markdown搞的乱七八糟的 ...

  5. iOS开发-Realm数据库

    Realm Realm-Object-c,见:https://realm.io/cn/docs/objc/latest/Realm官网:https://realm.io 使用流程 导入头文件#impo ...

  6. iOS 中SQLite数据库操作

    在iOS中实现SQLite数据库的操作:1.导入框架(libsqlite3.0.tbd) 2.导入头文件<sqlite3.h> 3.实现数据的增删改查 实现简单 SQLite数据库操作 的 ...

  7. iOS中的数据库—使用FMDB

    一.回顾 iOS中的数据存储方式 1.XML属性列表(plist) 写入OC的一些基本数据类型,不是所有对象都可以写入 2.Preference(偏好设置) 本质还是通过“plist”来存储数据,但是 ...

  8. ios中UIWebview和asiHttprequest的用法

    原文地址为:http://www.cnblogs.com/pengyingh/articles/2343062.htmlasiHttprequest的用法 它对Get请求的响应数据进行缓存(被缓存的数 ...

  9. iOS中UIButton控件的用法及部分参数解释

    在UI控件中UIButton是极其常用的一类控件,它的类对象创建与大多数UI控件使用实例方法init创建不同,通常使用类方法创建: + (id)buttonWithType:(UIButtonType ...

随机推荐

  1. Xapian的内存索引

    关键字:xapian.内存索引 xapian除了提供用于生产环境的磁盘索引,也提供了内存索引(InMemoryDatabase).内存索引.我们可以通过观察内存索引的设计,来了解xapian的设计思路 ...

  2. 【Spark篇】---Spark解决数据倾斜问题

    一.前述 数据倾斜问题是大数据中的头号问题,所以解决数据清洗尤为重要,本文只针对几个常见的应用场景做些分析 . 二.具体方法  1.使用Hive ETL预处理数据 方案适用场景: 如果导致数据倾斜的是 ...

  3. Netty(三) 什么是 TCP 拆、粘包?如何解决?

    前言 记得前段时间我们生产上的一个网关出现了故障. 这个网关逻辑非常简单,就是接收客户端的请求然后解析报文最后发送短信. 但这个请求并不是常见的 HTTP ,而是利用 Netty 自定义的协议. 有个 ...

  4. 一步一步教你如何用Python做词云

    前言 在大数据时代,你竟然会在网上看到的词云,例如这样的. 看到之后你是什么感觉?想不想自己做一个? 如果你的答案是正确的,那就不要拖延了,现在我们就开始,做一个词云分析图,Python是一个当下很流 ...

  5. 并发编程(八)—— Java 并发队列 BlockingQueue 实现之 ArrayBlockingQueue 源码分析

    开篇先介绍下 BlockingQueue 这个接口的规则,后面再看其实现. 阻塞队列概要 阻塞队列与我们平常接触的普通队列(LinkedList或ArrayList等)的最大不同点,在于阻塞队列的阻塞 ...

  6. 使用ML.NET + ASP.NET Core + Docker + Azure Container Instances部署.NET机器学习模型

    本文将使用ML.NET创建机器学习分类模型,通过ASP.NET Core Web API公开它,将其打包到Docker容器中,并通过Azure Container Instances将其部署到云中. ...

  7. 以语音评测的PC端demo代码为例,讲解口语评测如何实现

    本文由云+社区发表 作者:腾讯智慧教育 概述 腾讯云智聆口语评测(英文版)(Smart Oral Evaluation-English,SOE-E)是腾讯云推出的语音评测产品,是基于英语口语类教育培训 ...

  8. Django学习笔记(1)——初识Django

    一:Web框架介绍 框架,即framework,特指为解决一个开放性问题而设计的具有一定约束性的支撑结构,使用框架可以快速帮你开发特定的系统. Web框架是别人已经设定好的一个web网站模板,你学习它 ...

  9. 解读经典《C#高级编程》泛型 页122-127.章4

    前言 本篇继续讲解泛型.上一篇讲解了泛型类的创建.本篇讲解泛型类创建和使用的细节. 泛型类 上篇举了个我产品中用到的例子,本篇的功能可以对照着此案例进行理解. /// <summary> ...

  10. Python并发编程之谈谈线程中的“锁机制”(三)

    大家好,并发编程 进入第三篇. 今天我们来讲讲,线程里的锁机制. 本文目录 何为Lock( 锁 )?如何使用Lock( 锁 )?为何要使用锁?可重入锁(RLock)防止死锁的加锁机制饱受争议的GIL( ...