核心数据和Swift:数据模型

介绍

本系列第一篇文章中 ,我们了解了Core Data堆栈,它是Core Data应用程序的核心。 我们探索了托管对象上下文,持久性存储协调器和托管对象模型。

本文重点介绍Core Data应用程序的数据模型。 我们放大Xcode的数据模型编辑器,然后看一下实体,属性和关系。

先决条件

我在本系列的“核心数据”中介绍的内容适用于iOS 7+和OS X 10.10+,但是重点将放在iOS上。 在本系列中,我将使用Xcode 7.1和Swift 2.1。 如果您更喜欢Objective-C,那么我建议阅读我先前关于Core Data framework的系列文章

1.数据模型编辑器

首先从上一教程中下载项目,或者从GitHub克隆存储库。 在Xcode中打开项目,然后在“ 项目浏览器”中搜索Core_Data.xcdatamodeld 。 选择项目的数据模型时,Xcode自动显示数据模型编辑器。

Xcode中的核心数据模型编辑器

2.实体

在探索编辑器的用户界面之前,我们需要创建一个要使用的实体。 在数据模型编辑器的底部,单击“ 添加实体”按钮。 这将添加一个名称为Entity的实体 。 它将显示在数据模型编辑器左侧的“ 实体”部分中。 将实体名称更改为 在“ 实体”部分中双击该

将实体添加到核心数据模型

“什么是实体?” 您可能想知道。 为了带回数据库的类比,实体与数据库中的表具有可比性。 选择Person实体时,您会看到一个实体可以具有属性,关系和获取的属性。 现在不必担心获取的属性,它们是框架的更高级功能。

3.属性

通过单击“ 属性”表底部的加号按钮,为“ 人”实体赋予属性 。 双击属性名称并将其设置为 首先 。 从“ 类型”下拉菜单中,选择“ 字符串” 。 如果我们将此与数据库中的表进行比较, Person表现第一 String类型的有一栏。

在核心数据模型中向实体添加属性

即使我不想通过将实体与数据库表进行比较来使您感到困惑,它也使您更容易理解什么是实体和属性。 实际上,如果您使用SQLite数据库作为应用程序的后备存储,则Core Data将创建一个表供您存储Person实体的数据。 但是,这是我们不必且不必担心的事情。 请记住,核心数据不是数据库。

关系也是如此。 我们不需要担心核心数据如何跟踪关系。 实际上,Core Data确保仅在应用程序需要它们时才加载关系。 这是本系列后面的内容。

Person实体添加另外两个属性, 最后一个String类型,并且ageInteger 16类型。 此时,您选择的数字类型并不重要。 它告诉Core Data如何构造持久性存储并优化性能。

属性选项

可以通过数据模型检查器配置实体的属性。 选择“ 个人”实体的第一个属性,然后打开右侧的检查器。 使用数据模型检查器可以配置选定的属性。 至此,我们只对一些设置OptionalAttribute TypeDefault Value感兴趣。

可选的

将属性标记为可选意味着该属性可以为空,也可以保留为空白。 但是,在我们的示例中,我们要确保每个Person记录都有一个名字。 选择第一个属性后,取消选中“ 可选”以将其标记为必需。 默认情况下,新属性是可选的。

但是,将属性标记为必需会产生后果。 如果我们保存的人名记录没有有效的名字,则核心数据将引发错误。 这意味着在保存之前,我们需要确保已设置记录的第一个属性。

属性类型

由于多种原因,属性类型很重要。 它告诉Core Data应该以哪种格式保存属性,并且还将以指定格式将属性的数据返回给我们。 每种属性类型都有一组不同的配置选项。 将第一个属性的属性类型更改为Date,以查看类型为Date的属性的配置选项。

默认值

几种属性类型,例如StringDate ,都可以设置一个Default Value字段。 例如,如果需要属性,并且要确保将记录的属性插入数据库时​​,该属性具有有效值,这将很方便。

请注意,默认值仅在创建新记录时使用。 例如,如果通过将第一个属性设置为nil来更新现有的Person记录,则Core Data不会使用默认值填充第一个属性。 相反,Core数据将引发错误,因为我们根据需要标记了第一个属性。

4.关系

当您开始处理实体之间的关系时,核心数据才真正发挥作用。 让我们通过添加第二个名为Address的实体来了解其工作原理。 Address实体具有字符串街道数字城市国家类型的四个属性。

实体之间的关系具有许多定义特征,名称,目的地,关系的基数,逆关系以及关系的删除规则。

让我们通过在PersonAddress实体之间创建关系来更详细地探讨关系。

名称,目的地和可选性

通过选择“ 个人”实体并单击“ 关系”表底部的加号按钮来创建关系。 命名关系 地址并将“ 目的地”设置为“ 地址”实体。 这表明每个人记录都可以与一个地址记录相关联。

在核心数据模型中向实体添加关系

与属性一样,默认情况下关系是可选的。 这意味着,如果个人记录与地址记录没有关系,则不会引发验证错误。 让我们通过在右侧的数据模型检查器中取消选中“ 可选”复选框来更改此设置。

反向关系

此刻,该人可以与地址记录有关系。 但是,如果该人具有与之关联的地址记录,则该地址记录将不知道该人记录,因为此刻的关系是从PersonAddress的单向关系。 但是,Core Data中的大多数关系都是双向的,两个实体都知道该关系。

通过选择地址实体并创建一个以Person实体作为目的地的名为person的关系,来创建从Address实体到Person实体的逆关系。

在核心数据模型中向实体添加逆关系

即使我们创建了AddressPerson之间的逆关系,Xcode 也会给我们一些警告,告诉我们Person.address 应该具有逆,Address.person应该具有逆 。 我们做错了吗?

Core Data不够聪明,无法知道哪个关系是哪个关系的逆向关系。 这很容易解决。 选择Person实体,然后将address关系的Inverse设置为personperson关系。 如果现在选择“ 地址”实体,您将看到地址关系的逆关系已被设置为“ 人”关系。

数据模型图

当数据模型变得复杂时,关系会变得混乱和不清楚。 Xcode可以遮盖住您。 数据模型编辑器具有两种样式: tablegraph 。 在编辑器的右下角,您应该看到一个切换 ,“ 编辑器样式” ,可让您在两种样式之间进行切换。 单击右侧的按钮以切换到图形样式。

切换编辑器的样式

图的样式向您显示了我们到目前为止创建的对象图。 它向我们展示了我们创建的实体,它们的属性以及它们之间的关系。 但是,最有用的功能之一是数据模型实体之间关系的可视化表示。 两端带有箭头的线连接“ 人”和“ 地址” ,表示它们的双向关系。

图样式

一对多关系

到目前为止,我们创建的关系是一对一关系 ,一个人可以有一个地址,反之亦然。 但是,可能有几个人住在同一个地址。 我们如何将这些额外的信息包括在数据模型中?

关系的基数指定是一对一还是一对多关系。 让我们改变了地址实体的的关系,使之成为一对多的关系。 选择地址实体的人员关系,将其名称更改为人员以反映多对多关系,然后在右侧的检查器中将关系类型设置为“多对多 ”。

在核心数据模型中向实体添加一对多关系

关系的名称并不重要,但是表明这是一对多的关系。 请注意,数据模型图会自动更新。 Person实体的关系端点有两个箭头,表示该关系的多对多性质。

多对多关系

等一下。 一个人可能与一个以上的地址相关联吗? 一个人可以有一个工作地址和一个家庭住址。 对? Core Data通过创建多对多关系来解决此问题。 选择Person实体的地址关系,将其名称更改为address ,并将关系Type设置为To Many 。 数据模型图将更新的关系显示为两端带有两个箭头的线。

在核心数据模型中向实体添加多对多关系

自反关系

核心数据实现关系的方式非常灵活。 关系的目标实体甚至可以与源实体相同。 这被称为自反关系。 也可能具有相同类型的不同名称的多个关系。 例如,一个人可以有一个母亲和一个父亲。 两种关系都是自反的,唯一的区别是关系的名称。

删除规则

关系的一端的记录被删除时会发生什么? 如果您将核心数据视为数据库,那么答案将是显而易见的。 但是,核心数据不是数据库。

假设您有一个Account实体与一个User实体有一对多的关系。 换句话说,一个帐户可以有多个用户,并且每个用户都属于一个帐户。 删除用户会怎样? 删除帐户会怎样? 在“核心数据”中,每个关系都有一个删除规则,该规则可清楚说明在这些情况下会发生什么。

删除规则确保您不必担心删除记录时显式更新持久性存储。 核心数据会注意这一点,以确保对象图保持一致状态。

选择人员实体的地址关系,然后打开右侧的检查器。 Delete Rule菜单具有四个选项, No ActionNullifyCascadeDeny

没有行动

如果选择No Action ,则Core Data不会更新关系或将关系通知给源记录。 这意味着该关系的源记录仍然认为它与已删除的记录有关系。 这很少是您想要的。

无效化

当删除目标记录时,此选项将关系的目标设置为null。 这是关系的默认删除规则。 例如,如果关系是可选的,则可以应用此删除规则。

级联

如果“从人员地址”的关系设置为Cascade ,则删除人员记录也将删除与该人员记录关联的所有地址记录。 例如,这在需要关系并且没有关系就不能存在或不应该存在记录的情况下很有用。 例如,如果用户未与帐户关联,则该用户不应存在。

拒绝

从某种意义上说, DenyCascade的逆。 例如,如果我们有一个帐户实体与一个删除规则设置为“拒绝”用户实体具有一对多关系,则只有在没有与之关联的用户记录的情况下,才能删除该帐户记录。 这样可以确保没有帐户记录就不会存在用户记录。

结论

在本教程中,我们仔细研究了Core Data应用程序使用的数据模型。 现在,您应该熟悉实体,属性和关系,并且应该能够使用Xcode的数据模型编辑器创建它们。

Core Data非常擅长管理关系,而Xcode的数据模型编辑器使创建和管理实体之间的关系变得容易。 实体之间的关系功能强大且易于配置。 删除规则可确保Core Data管理的对象图保持健康且处于一致状态。

在下一篇文章中,我们开始动手工作,并开始使用Core Data。 您将学习如何创建,读取,更新和删除记录,并熟悉NSManagedObjectNSFetchRequest

翻译自: https://code.tutsplus.com/tutorials/core-data-and-swift-data-model--cms-25067

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
接着分析 (result (type_ident (component id='Bool' bind=Swift.(file).Bool))) (brace_stmt range=[re.swift:1:59 - line:14:1] (pattern_binding_decl range=[re.swift:2:5 - line:2:33] (pattern_named type='[UInt8]' 'b') Original init: (call_expr type='[UInt8]' location=re.swift:2:19 range=[re.swift:2:13 - line:2:33] nothrow (constructor_ref_call_expr type='(String.UTF8View) -> [UInt8]' location=re.swift:2:19 range=[re.swift:2:13 - line:2:19] nothrow (declref_expr implicit type='(Array<UInt8>.Type) -> (String.UTF8View) -> Array<UInt8>' location=re.swift:2:19 range=[re.swift:2:19 - line:2:19] decl=Swift.(file).Array extension.init(_:) [with (substitution_map generic_signature=<Element, S where Element == S.Element, S : Sequence> (substitution Element -> UInt8) (substitution S -> String.UTF8View))] function_ref=single) (argument_list implicit (argument (type_expr type='[UInt8].Type' location=re.swift:2:13 range=[re.swift:2:13 - line:2:19] typerepr='[UInt8]')) )) (argument_list (argument (member_ref_expr type='String.UTF8View' location=re.swift:2:29 range=[re.swift:2:21 - line:2:29] decl=Swift.(file).String extension.utf8 (declref_expr type='String' location=re.swift:2:21 range=[re.swift:2:21 - line:2:21] decl=re.(file).check(_:_:).encoded@re.swift:1:14 function_ref=unapplied))) )) Processed init: (call_expr type='[UInt8]' location=re.swift:2:19 range=[re.swift:2:13 - line:2:33] nothrow (constructor_ref_call_expr type='(String.UTF8View) -> [UInt8]' location=re.swift:2:19 range=[re.swift:2:13 - line:2:19] nothrow (declref_expr implicit type='(Array<UInt8>.Type) -> (String.UTF8View) -> Array<UInt8>' location=re.swift:2:19 range=[re.swift:2:19 - line:2:19] decl=Swift.(file).Array extension.init(_:) [with (substitution_map generic_signature=<Element, S where Element == S.Element, S : Sequence> (substitution Element -> UInt8) (substitution S -> String.UTF8View))] function_ref=single) (argument_list implicit (argument (type_expr type='[UInt8].Type' location=re.swift:2:13 range=[re.swift:2:13 - line:2:19] typerepr='[UInt8]')) )) (argument_list (argument (member_ref_expr type='String.UTF8View' location=re.swift:2:29 range=[re.swift:2:21 - line:2:29] decl=Swift.(file).String extension.utf8 (declref_expr type='String' location=re.swift:2:21 range=[re.swift:2:21 - line:2:21] decl=re.(file).check(_:_:).encoded@re.swift:1:14 function_ref=unapplied))) ))) (var_decl range=[re.swift:2:9 - line:2:9] "b" type='[UInt8]' interface type='[UInt8]' access=private readImpl=stored writeImpl=stored readWriteImpl=stored)
06-10

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值