您不能直接在 Core Data 中执行此操作,因为与上面的示例不同,Core Data 还必须维护关系图。
要理解这一点,假设您使用上面的示例代码手动设置关系。现在假设您有一个SavedDie
保存在savedDice
and immediateRolls
of中的类PlayerState
。如果您希望每个SavedDie
实例都引用 ,那么PlayerState
创建一个指向拥有的指针PlayerState
会很容易,但是您如何知道PlayerState
它存储在哪个属性中。更重要的是,您如何强制执行它以使相同的SavedDie
对象不会出现在两个属性或两个或多个单独的PlayerState
对象?
创建 Core Data 是为了自动管理所有这些,它使用实体图来做到这一点。实体不是类。相反,它们是主要对象之间关系的抽象表示。实体图不会让您让一个实体与另一个实体有两个关系,因为不可能跟踪实时数据对象的哪些实例相互关联。
有两种方法可以解决您的问题。
(1) 使用实体继承:您创建一个Die
实体并使用您希望它拥有的所有属性对其进行设置。然后创建两个子实体:SavedDie
和ImmediateDie
. 然后你设置关系:
PlayerState.savedDie<-->SavedDie.playerState
PlayerState.immediateDie<-->>ImmediateDie.playerState
(2) 使用获取的关系:在这种情况下,你有一个Die
实体和一个关系:
PlayerState.Die<-->>Die.playerState
...但你有一个属性Die
,使每个实例都保存或立即。然后创建两个获取的关系,每个关系的谓词查找标志的不同状态。
(3) 使用链接实体:在此技术中,您使用中间实体将两个主要实体以多种关系联系在一起,如下所示:
PlayerState{
//...some attributes
savedDice<-->>PlayerToSavedDie.playerState
immediateDice<-->>PlayerToImmediateDie.playerState
}
ToDie{
die<-->SaveDie.player
}
PlayerToSavedDie:ToDie{ //...subentity of ToDie
//... no attributes
playerState<<-->PlayerState.savedDice
}
PlayerToImmediateDie:ToDie{ //...subentity of ToDie
//... no attributes
playerState<<-->PlayerState.savedDice
}
Die{
player<-->ToDie.die
}
这样,您Die
只需删除一个链接关系并创建另一个链接关系,就可以在关系周围移动实例。由于Die.player
指向ToDie
它的点将接受任何一个PlayerToSavedDie
或PlayerToImmediateDie
在该关系中。
您使用这些技术中的哪一种取决于您的数据模型的需求。如果一个关系中的逻辑 Die 对象从不跳转到另一个关系,则使用 (1)。如果保存或即时数据是逻辑 Die 对象本身的重要属性,请使用 (2)。如果逻辑 Die 对象需要在关系之间移动,并且保存或即时数据不是逻辑 Die 对象的一部分,则使用 (3)。
所有这一切似乎需要做很多工作,但您必须记住一件重要的事情:关系与属性一样重要!如果模型的关系不能反映模型模拟的真实世界对象、事件或条件,则模型将无法工作。你应该期望花一些时间思考和管理关系。
Core Data 使关系管理变得容易了一百倍,但仍然需要一些工作。