• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

使用Realm和Swift创建ToDo应用

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

原文出处: HOSSAM GHAREEB   译文出处:Prayer’s blog(@EclipsePrayer)   

智能手机的快速发展的同时,涌现出了很多对开发者友好的开发工具,这些工具不仅使得开发变得更加容易,同时也保证了性能和产品质量。如今,想要在 App Store 占据一席之地,并非易事。想要使得应用易于扩展就更加困难了。当你成功获得百万量级的用户时,应用中的每一个细节都不能放过,并且需要在很短的时间完成对细节的打磨。和数据库打交道,是很多开发者都会面临的一个问题。相信我们每个人都会因为数据库引起的各种问题而头疼不已,对于数据库,我想如今我们只有两种选择:SQLite 和 Core Data。我是 Core Data 的忠实粉丝,它对记录(records)的处理和持久化数据的能力非常强大,但是我意识到,在开发应用的过程中,我在 Core Data 上浪费了太多的时间。最近,我无意中发现了 Realm,一个可以替代 SQLite 和 Core Data 的更好的解决方案。

Realm 是什么?

Realm 是一个跨平台的移动终端数据库,支持 iOS(Swift 和 Objective-C 语言都支持)和 Android。Realm 的目的就是提供比 SQLite 和 Core Data 更好更快的数据库支持。它不仅仅是更好和更快,而且更加易于使用,短短几行代码就可以完成很多操作。Realm 完全免费,你可以随意使用它。Realm 是为移动设备而生的,因为在过去的十年中,移动终端的数据库技术没有任何的革新。现在如果和移动终端的数据库打交道,你只有一种选择,使用 SQLite 或者是底层封装了 SQLite 的技术比如 Core Data。Realm 的目的是更加易用,它并不是一个建立在 SQLite 之上的 ORM,而是一个基于自己的持久化引擎,简单并且快速的面向对象移动数据库。

为什么选择 Realm ?

Realm拥有令人难以置信的速度并且使用起来非常简单,你会发现,无论是想完成数据库的读还是写操作,都只需要短短的几行代码。下面我会列出它的所有优势,并说明为什么 Realm 是你在移动应用上数据库的不二选择:

  • 安装简单:在下一个章节——如何使用 Realm 中你会了解到,安装 Realm 会比你想象的更为简单。使用简单的 Cocoapods 命令,你就可以完成所有的安装工作。
  • 速度更快:使用 Realm 库操作数据库的速度非常快。它比 SQLite 和 CoreData 都更加快速,这里有它们之间的比较指标作为证据。
  • 跨平台:Realm 的数据库文件是跨平台的,可以在 iOS 和 Android 间共享。无论你是使用 Java,Objective-C 或者 Swift,都可以使用相同的抽象模型访问。
  • 易于扩展:如果你的移动应用需要处理大量的用户数据记录,数据库的可扩展性就显得十分重要。在开始着手开发应用之前,这一点就应该被考虑在内。Realm 提供很好的可扩展性,在操作大量的数据时,速度也非常之快。选择使用 Realm 可以为你的应用带来更快的速度和更加流畅的用户体验。
  • 规范的文档和很好的支持:Realm 提供了大量条理清晰、易于阅读的文档。如果你有任何的问题,你也可以通过 Twitter,Github 或 Stackoverflow 来联系它们获得帮助。
  • 可信任:Realm 已经被大量的初创公司和大公司用于它们的移动应用中,像 Pinterest,Dubsmash 和 Hipmunk。
  • 免费:除了以上这些极好的优点以外,它还是完!全!免!费!的!

让我们开始动手吧

让我们开始学习 Realm,使用它来构建一个使用 Swift 语言的简单的 iPhone 应用。所完成的 demo 程序是一个简单的 Todo 应用。用户可以增加任务清单,每个任务清单都能够包含多个任务。任务拥有名称,备注,到期日期,可以添加图片,并且拥有一个布尔值来表示该任务是否已经完成。在开始创建 Xcode project 之前,我们需要先配置好 Xcode,安装使用 Realm 所需的工具。

环境要求

请注意需要满足下列要求

  • iOS 8 及更高的版本,OS X 10.9 及更高的版本
  • Xcode 6.3 及更高版本
  • Realm 有两个发行版,一个针对 Swift 2.0,另一个针对 Swift 1.2。我们推荐您使用 Swift 2.0 的版本。当然你也可以使用针对 Swifit 1.2 的版本,但是以后这个版本 Reaml 不会再进行更新支持,所以为了保险起见,使用 Swift 2.0 对应的版本,是个更好的选择。

配置 Xcode 和所需的工具

在开始配置 Xcode 项目之前,请确保运行环境已经正确安装了 CocoaPods,我们将使用它来为项目安装 Realm。如果对 CocoaPods 不熟悉,你可以查看在线的教程,这些教程的材料足够让你明白如何开始使用它。

现在,使用 Single View Application 项目模板创建一个 Xcode 工程,命名为 RealmTasks 或者其他你喜欢的名字。请确保选择 Swift 作为开发语言。之后使用终端进入该工程目录,使用如下命令来初始化 CocoaPods:

 
 
 
 
 
Objective-C
 
1
init

然后使用 Xcode 打开生成的 Podfile 文件,在 target 之后,添加 pod 'RealmSwift',修改完之后,应该是下面这个样子:

下面运行 pod install 命令来把 Realm 下载到项目中。完成之后,你会在你的工程文件目录发现一个新生成的 Xcode 工作空间。请确保打开 RealmTasks.xcworkspace 而不是 xcodeproj。打开工作空间后,你会得到下面的情形:

现在就可以在 Xcode 中使用 Realm 啦,但是我们将安装下面的小工具来让使用 Realm 的过程更加容易。

安装 Realm Xcode 插件

Realm 开发团队提供了一个生成 Realm 模型非常有用的工具。为了安装这个插件,我们要使用 Alcatraz。如果你不知道 Alcatraz 是什么的话,这里解释一下,它是一个简单有用的开源包管理工具,它可以让你无需任何配置,自动地为 Xcode 安装插件,文件模板和颜色主题。为了安装 Alcatraz,你只需将以下代码复制到终端中执行,之后重启 Xcode:

 
 
 
 
 
 
Objective-C
 
1
//raw.githubusercontent.com/supermarin/Alcatraz/master/Scripts/install.sh | sh

然后在 Xcode 中,选择 Window->Package Manager,如下:

然后在弹出的窗口中,你可以选择安装你喜欢的插件或者文件模板,在搜索框中你可以搜索你喜欢的插件、配色。在搜索框输入“Realm”,在出现的结果中选择“RealmPlugin”,点击INSTALL按钮

Realm Browser

给大家介绍的最后一个工具是 Realm 浏览器。这个浏览器可以帮助你阅读和编辑你的.realm数据库文件。这些文件在应用程序中被创建,在数据库表中保存了所有的数据实体(entities),属性(attributes)和记录(records)。之前我们说过,这些数据库文件可以在不同的平台像 iOS 和 Android 平台间共享。想要下载 最新版本的 Realm 浏览器,请访问 iTunes store。打开 Realm 浏览器,选择 Tools->Generate demo database。它会帮你生成 realm 数据库测试文件,你可以使用该浏览器打开和编辑它的内容。当你打开的时候,你会看到像下面的内容:

在 RealmTestClass1 中,它拥有 1000 条记录,显示了多种不同的参数类型。我们会在下节介绍支持的属性类型。

现在,Realm 的所有准备工作都已就绪,那我们开始动手把。

数据库模型类

好戏才刚刚开始。首先我们来创建模型类或者说我们的数据库。为了创建 Realm 数据模型类,你只需要简单地新建一个普通的 Swift 类继承自 Object 就可以了。因为 Realm 数据模型类的基类是 Object,所以 Object 的子类都可以扩展为 Realm 的模型类。在创建类之后,就可以添加属性了。Realm 支持以下多种数据类型:

  • Int, Int8, Int16, Int32, 和 Int64
  • Boolean
  • Float
  • String
  • NSDate
  • NSData
  • 继承自 Object 的类 => 作为一对一关系 (Used for One-to-one relations)
  • List

Realm 中的 List 可以包含多个 Object 实例,参考上面 demo 数据库的截图,最后一列表示在其他数据表中的存在的一组引用。在和 Realm 模型类打交道的时候,使用的方式和其他 Swift 类一样。例如,你可以添加方法或者遵循指定的协议。

多说无益,来看代码

现在让我们使用之前在 Xcode 中安装的 Realm 插件来新建一个 Realm 类。打开 Xcode,新建文件,选择 Realm:

然后选择 Swift 语言,类名我们输入 Task。会得到如下结果:

现在,可以向 Task 数据模型中添加属性了。

Properties

我们需要在数据模型中添加需要的属性。该例子中,Task 需要有 name (String), createdAt (NSDate), notes (String), 和 isCompleted (Bool)这些属性。添加这些之后,代码应该像下面酱紫:

 
 
 
 
 
Objective-C
 
1
2
3
4
5
6
7
8
9
10
11
12
13
{
 
)
false
 
// Specify properties to ignore (Realm won't persist these)
 
//  override static func ignoredProperties() -> [String] {
//    return []
//  }
}

我们已经为 Task 添加了属性,所有的属性前面都加了 dynamic var ,这使得属性可以被数据库读写。

接下来,我们要创建 TaskList 模型类,用来存储 Task 实例:

 
 
 
 
 
Objective-C
 
1
2
3
4
5
6
7
8
9
10
11
12
{
 
)
)
 
// Specify properties to ignore (Realm won't persist these)
 
//  override static func ignoredProperties() -> [String] {
//    return []
//  }
}

TaskList 模型类拥有 name,createAt 和一个包含 Task 的 List 属性。需要注意的是:

  1. List 用来表示一对多的关系:一个 TaskList 中拥有多个 Task
  2. List 和 Array 在使用上非常相似,所用的方法和访问数据的方式(索引和下标)都相同。List 后标明了数据类型,所包含的所有对象都应该是相同类型的。
  3. List 是泛型,这也是为什么我们没有在声明前面加上 dynamic 的原因,因为在 Objective-C 运行时无法表示泛型属性。

在 Realm 中创建数据关系非常直观,就像在之前实现中你看到的一对多关系那样。在使用一对一的关系时,我们将使用 Object 类型,来看下面的例子:

 
 
 
 
 
Objective-C
 
1
2
3
4
5
6
7
{
}
 
{
?
}

上面的例子中,owner 属性表示 Car 和 Person 之间的一对一数据关系。

现在基本的数据模型都已经创建好了。接下来我们会在做一个 ToDo 应用的同时,来讨论 Realm。首先,从这里下载 app,在 Xcode 7 或更高的版本中运行,就像下面这样:

在项目中,我添加了两个视图控制器: TasksViewController 和 TaskListViewController。第一个视图控制器用来显示单个 task,第二个视图控制器用来显示所有的 TaskList。在 list 视图中,点击 + 按钮来添加一个任务清单。选择一个任务清单将会详情视图。你可以在这里添加多个 task。

了解了 demo 的大体思路之后,现在让我们来看看如何向 Realm 数据库中添加一个新的任务清单。为了实现这个功能,需要如下处理:

  1. 创建 TaskList 实例对象,并将其保存到 Realm 数据库中
  2. 向数据库中查询 list 数据,来更新 UI

为了在 Realm 中保存数据,你只需要实例化继承自 Object 的数据模型类,然后将对象写入到 Realm 中,下面是示例代码:

 
 
 
 
 
 
Objective-C
 
1
2
3
4
5
6
7
8
9
10
11
)
 
)
 
)
)
 
)

通过实例化 TaskList 类,我们创建了一个任务清单,之后设置了它的属性。随后我们创建了 3 个 Task 类型的对象。这里我们演示了创建 Realm 对象的三种途径:

  1. wish1 的实例化方式:简单的实例化 Realm 类,然后设置属性
  2. wish2 的实例化方式:传入一个字典,字典中的 key 为属性名,值为要设置的值
  3. wish3 的实例化方式:使用数组传入的方式。数组中值的顺序需要和模型类中的声明顺序一致。

嵌套对象

在 Realm 中还可以是使用嵌套的方式来创建对象。在一对一关系和一对多关系的时候,你可以使用这种方式,这时候,一个类型对象的初始化需要一个或多个另一个类型的对象。面临这种情况的时候,你可以选择上面的第二或者第三种方法,使用一个字典或者一个数组来表示一个对象:

 
 
 
 
 
 
Objective-C
 
1
)

在上面的代码中,我们创建了一个电影清单,并设置了清单名称、创建时间和清单内容,清单内容包括多个 task。每个 task 使用数组的方式来创建,例如 [“The Maze Runner”, NSDate(), “”, true] 表示一个task,内容分别对应了名称,创建时间,备注和是否已经完成。

使用 Realm 持久化对象

现在你应该知道了如何在 Realm 中创建和使用对象,但是为了能够在应用程序重新启动的时候使用这些数据,需要使用写事务将它们持久化到 Realm 的数据库中。当使用 Realm 来持久化数据的时候,只要这些对象已经存储成功,你可以在任何线程中获取这些对象。一个 Realm 实例表示一个 Realm 数据库。可以像下面一样实例化它:

 
 
 
 
 
Objective-C
 
1
)

我们常常将上面这行代码写在 AppDelegate.swift 文件的顶端(译者注:类之外,全局变量),这样就可以在整个项目中获得该对象的引用。之后便可以很方便地调用它的读和写方法:

 
 
 
 
 
Objective-C
 
1
2
3
in
)
}

首先,uiRealm 对象已经在 AppDelegate 中创建,在整个 app 中都可以使用。Realm 对象在每个线程中都应该只被创建一次,因为它不是线程安全的,不能在不同的线程中共享。如果你想要在另一个线程中执行写操作,那么就需要创建一个新的 Realm 对象。我将这个实例命名为 uiRealm,就是因为它应该只在 UI 线程中被使用。

现在让我们回到我们的 app 中,我们需要在用户点击 Create 按钮的时候保存任务列表。在TasksViewControllerdisplayAlertToAddTask方法中,我们有一个 createAction 对象:

 
 
 
 
 
 
Objective-C
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
in
 
text
 
{
// update mode
in
!
)
)
}
{
 
)
!
 
in
 
)
)
)
}
 
}

在上面的代码中,我们从 TextField 中获取到任务名称,调用 Realm 的鞋方法来保存任务列表。

请注意,当你同时进行多个写操作的时候,他们会相互阻塞,阻塞住他们所运行的线程。所以应当考虑在 UI 之外的线程中来进行操作,另外需要注意的是,在进行写事务的时候,读操作并不会造成阻塞。这非常有用,尤其是当你在后台进行写操作的时候,用户可能会在不同界面切换,而这时候可以进行读操作。

检索数据

现在你已经学会了如何在 Realm 中写数据,下面我们来看看如何检索数据。在 Realm 中检索数据的方式非常直观。Realm 提供了很多选项来过滤出你想要的数据。在 Realm 中进行查找操作的时候,它将会返回一个 Results 对象。可以把 Results 简单地当做是 Swift 的数组,因为它们的接口非常类似。

当得到 Results 实例的时候,已经从磁盘中直接获取到了数据。对这些数据的任何操作(使用事务)将会影响到磁盘上的数据。在 Realm 中来检索数据,只需要调用对象的方法,并将类名作为参数传进去。让我们看看如何使用这种方式来读取 TaskLists 并更新 UI:

我们在 TasksListsViewController 中定义了该属性:

 
 
 
 
 
Objective-C
 
1
!

然后实现了 readTasksAndUpdateUI 方法:

 
 
 
 
 
Objective-C
 
1
2
3
4
5
{
)
)
)
}

在 tableView(_:cellForRowAtIndexPath:_) 方法中,我们将显示列表的名称,还有每个列表内的任务个数:

 
 
 
 
 
 
Objective-C
 
1
2
3
4
5
6
7
8
9
10
{
 
)
 
]
 
name
!
}

代码逻辑非常直观吧。最后需要做的就是在 viewWillAppear 中调用 readTasksAndUpdateUI 方法,来确保总是显示数据更新之后的视图。

 
 
 
 
 
Objective-C
 
1
2
3
{
)
}

上面展示了如何使用 Realm 来进行任务列表的读写操作。接下来,我们来看看如何进行数据更新和删除操作。在开始之前,先来看看项目中的修改和删除不分的相关代码。

首先在 TaskListsViewController 中,我们用一个布尔值 isEditingMode 来表示是在正常状态还是编辑状态:

 
 
 
 
 
Objective-C
 
1
false

当 Edit 按钮被点击的时候,将会调用 didClickOnEditButton 方法:

 
 
 
 
 
Objective-C
 
1
2
3
4
{
isEditingMode
)
}

这个方法会使用 table view 的 setEditing 方法来开启或禁用 UITableView 的编辑模式。在表格视图中,默认的编辑操作是删除,但是从 iOS 8.0 开始,增加了一个 editActionsForRowAtIndexPath 方法来自定义一些操作,这些操作在在用户滑动表格 cell 的时候出现。

我们将使用该方法来添加两个功能,删除和编辑,代码如下:

 
 
 
 
 
 
Objective-C
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
in
 
//Deletion will go here
 
]
in
)
)
)
}
in
 
// Editing will go here
]
    
}
]
}

这里我们使用 UITableViewRowAction 添加了两个操作,方法中定义了操作的 styletitle 和 handler。当在滑动 cell 或者以其他方式进入编辑模式的时候,会像下面这样:

以上就是在进行删除和更新操作时候的 UI 代码逻辑。

删除对象

想要从 Realm 数据库中删除对象或者数据,你只需要调用 Realm 对象的 delete 方法,同时将该对象作为参数传入。当然,这些操作会在写事务中完成。来看一下下面的代码的工作方式,我们从 Realm 数据库中删除了一个任务列表:

 
 
 
 
 
Objective-C
 
1
2
3
4
5
]
in
)
)
)

在删除之后,我们调用了 readTasksAndUpdateUI 方法来读取数据并更新 UI。

在 Realm 中,还有一个方法叫做 deleteAll,它允许你删除数据库中所有 class 的所有数据。如果你想为当前用户持久化数据,但是在他退出登录的时候抹掉所有的相关数据,这个方法将会十分有用。

 
 
 
 
 
Objective-C
 
1
2
3
in
)
)

 

更新 Objects

在 Realm 中有多种方式可以来更新 object,但是这些方法都应该在写事务中完成。下面我们来看一些更新对象的方式。

使用 properties

你可以通过直接在 Realm 的写闭包中设置 property 的值来更新数据。例如,在 TasksViewController 中,我们可以简单地设置属性值来更新任务的状态信息:

 
 
 
 
 
Objective-C
 
1
2
3
in
true
)

使用主键

Realm 支持将某个 string 或 int 类型的属性设置为主键。当使用 add() 方法来创建 Realm 对象时,如果有相同主键的对象存在,就会更新这个对象的值。下面是示例代码:

 
 
 
 
 
Objective-C
 
1
2
3
4
5
6
7
8
9
)
1
// Updating User with id = 1
{
)
}

这里的 id 属性为主键。如果 id 为 1 的用户存在,Realm 会更新相应的对象。如果不存在,Realm 将会把该对象存入数据库中。

使用 KVC (Key-Value Coding)

如果你是 iOS 开发的老手,那么对 Key-Value Coding 肯定不会陌生。Realm 的类型,像 Object,Results 和 List,都可以使用 Key-Value Coding。该特性可以帮助你在运行时设置或更新属性值。另外一个支持 KVC 的好处是,可以在无需遍历每个对象的情况下,批量更新对象数据。这么说你可能不是很理解,我们来看个例子:

 
 
 
 
 
Objective-C
 
1
2
3
4
)
in
)
}

在上面的代码中,使用查询语句来请求所有的 Task 对象,之后将所有得到的对象的 isCompleted 属性设置为 true。可以看出,将 Realm 中的所有 tasks 标记为已完成,仅仅只用了一行代码。

让我们回过头来看看我们的 ToDo 应用。如果仔细观察 displayAlertToAddTaskList 方法,你会看到如下代码片段:

 
 
 
 
 
Objective-C
 
1
2
3
4
5
// update mode
in
!
)
)

当用户遍历列表名称的时候,上面的代码会被调用。通过设置 name 属性的方式,就更新了数据库中的内容。

显示任务列表

我们将一起看看 TaskListViewController 的大部分代码。现在让我们打开 TasksViewController 来看看,这个视图控制器用来显示任务清单中的任务项。视图控制器拥有一个 UITableView, 该视图有两个 section:完成的任务和未完成的任务。在 TasksViewController 中,有如下属性:

 
 

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap