掌握CoreData(第3部分:核心数据中的CRUD)
为了演示核心数据的基础知识,让我们创建一个单视图iOS应用,并选择“ 使用核心数据”或下载入门项目。
如果您有一个现有项目,但未选中“ 使用核心数据”复选框,则仍然可以添加核心数据,我将在后面的部分中进行介绍。 创建项目后,您将看到添加的文件如CrudOperationCoreData.xcdatamodeld 。
我将在Todo应用程序上演示CRUD操作。 最终版应用可以执行以下功能
- 用户可以添加任务
- 用户可以删除任务
- 用户可以看到所有任务
当您使用CrudOperationCoreData.xcdatamodeld文件时,您将看到一个工具,可用于配置代表数据模型的实体。 您可以为每个实体定义一些事物,但对我们而言, 属性和关系将是最重要的。
到目前为止,我们已经完成了创建并获得核心数据支持的项目。 在CrudOperationCoreData.xcdatamodeld中,我们用数据库术语定义Entity或表,并定义属性(数据库术语列)。 “ xcdatamodeld ”是一个称为“ 受管对象模型 ”的文件,其中,如上一部分所述,定义了应用程序的所有架构。 我说过,我们将 深入讨论时 将称为 第2部分 ,因为我们在该部分的理论方面进行了很多讨论。
托管对象模型
托管对象模型是一组对象,这些对象一起构成了一个蓝图,描述了您在应用程序中使用的托管对象
您的应用程序中使用的模型对象的架构
正如我们在第2部分中讨论的那样,我们需要创建Core Data堆栈才能使用Core Data,但是我们还没有创建堆栈。 事实是,当我们在创建项目时选中“ 使用核心数据”时,它会自动在AppDelegate文件中创建堆栈代码。 打开AppDelegate文件
当您看到代码时,您几乎看不到您在Core Data stack Part 2中学到的任何东西。 但是您可以看到NSPersistentContainer的惰性属性
NSPersistentContainer
NSPersistentContainer通过处理托管对象模型(NSManagedObjectModel),持久性存储协调器(NSPersistentStoreCoordinator)和托管对象上下文(NSManagedObjectContext)的创建,简化了核心数据堆栈的创建和管理。 可从iOS 10获得
当您跳到NSPersistentContainer类定义时,您将在此处看到所有Core Data堆栈组件。
创建记录核心数据
将记录添加到核心数据的过程具有以下任务
- 从appdelegate单例对象引用persistentContainer
- 从persistentContainer创建/访问单例托管对象上下文
- 使用Task创建一个实体(代表ToDo任务)
- 使用此任务实体创建新记录
- 设置每个键的记录值
- 将其保存到磁盘(永久存储)。
在从核心数据存储中保存或检索任何内容之前,首先需要动手使用NSManagedObjectContext。 您可以将托管对象上下文视为用于处理托管对象的内存“便签本” 。
考虑将新的托管对象保存到Core Data中的过程分为两个步骤
- 首先,将新的托管对象(任务)插入到托管对象上下文中
- 高兴的是,您在托管对象上下文中提交更改以将其保存到磁盘。
Xcode已经生成了一个托管对象上下文,作为新项目模板的一部分。 请记住,只有在开始时选中“ 使用核心数据”复选框,才会发生这种情况。 此默认托管对象上下文作为应用程序委托中NSPersistentContainer的单例属性存在。 要访问它,您首先需要获得对应用程序委托的引用。
数据物理存储/磁盘存储的位置
默认情况下,Core Data堆栈使用SQLite作为后端中的持久存储。 您可以在文档目录中看到扩展名为.sqlite的 SQLite文件。 在DB Browser For SQLite中打开此文件。 您将看到我们刚刚添加并提交的数据,现在已物理存储。 Save方法将所有数据从NSManagedObjectContext (内存)移至持久性存储(磁盘) 。
现在,NSManagedObjectContext缓存了该数据。 下次如果要获取此数据,它将首先从缓存(NSManagedObjectContext)中检查是否找到了它,它将从缓存中返回,否则将进入持久性存储,这将比从缓存中获取花费更多的时间。
从核心数据中获取记录
从核心数据中获取记录的过程具有以下任务
- 从appdelegate单例对象引用persistentContainer
- 从persistentContainer创建/访问单例托管对象上下文
- 创建了一个提取请求,以仅过滤实体名称为Task的 NSManagedObject。
- 您将获取请求交给了托管对象上下文,以完成繁重的工作。 fetch(_ 🙂返回满足fetch请求指定条件的托管对象数组。
NSFetchRequest
NSFetchRequest用于从持久性存储中检索数据。 当我们深入使用NSFetchRequest时,我们将在后面的部分中讨论。 像save()一样, fetch(_ 🙂也可能引发错误,因此您必须在do块中使用它。 如果在获取期间发生错误,则可以检查catch块内部的错误并做出适当响应。
生成并运行该应用程序。 随即,您会在控制台中看到显示“保存待办事项”列表任务
从核心数据中删除记录
从核心数据中删除记录的过程具有以下任务
- 从appdelegate单例对象引用persistentContainer
- 从persistentContainer创建/访问单例托管对象上下文。 此应用程序具有一个单例托管对象上下文,该上下文最初具有与持久性存储相同的数据(内存中的副本),并充当高速缓存。 您可以在该暂存器中进行更改,如果不需要任何更改,则可以执行撤消操作以放弃这些更改,并且如果执行保存操作,它将把managedObjectContext数据转储到持久性存储(磁盘)中。
- 创建了一个提取请求,以仅过滤实体名称为Task的 NSManagedObject。
- 遍历所有对象并在上下文中调用delete方法。 此步骤将删除该上下文中的对象,并且因为我们仅从缓存中删除了,所以持久性存储中将拥有该对象。
- 最后,我们将更改提交到持久存储。 现在上下文和持久性存储都具有相同的状态。 您可以从sqlite文件中看到没有数据,如图3所示。
摘要
我们刚刚完成了CRUD操作的编码部分。 在这一部分中,我们使用KVC访问实体的属性,而不是使用更自然的对象样式方式。 正如我们在第1部分中所述。
核心数据以一种看起来非常面向对象的方式存储我们的代码。 实体是指类,属性是指var,关系是指var指向其他类
接下来是什么?
在下一部分中,我们将以面向对象的方式执行CRUD操作
有用的链接
https://store.raywenderlich.com/products/core-data-by-tutorials
https://www.objc.io/issues/4-core-data/core-data-overview/
https://zh.wikipedia.org/wiki/Object-relational_mapping
https://cocoacasts.com/what-are-core-data-entities-and-attributes
https://cocoacasts.com/what-is-the-core-data-stack
https://developer.apple.com/library/archive/documentation/DataManagement/Devpedia-CoreData/coreDataStack.html
https://medium.com/@ankurvekariya/core-data-crud-with-swift-4-2-for-beginners-40efe4e7d1cc
https://www.raywenderlich.com/7569-getting-started-with-core-data-tutorial
https://developer.apple.com/library/archive/qa/qa1952/_index.html