首先,Core Data 的真正目的不是持久化,而是创建模型-视图-控制器设计应用程序的模型层。这意味着 Core Data 首先是一个模型/模拟 API,其次是一个持久性 API。因此,Core Data 数据模型应该准确地表示现实世界对象、条件或事件的属性以及它们之间的关系。
因此,当您着手构建数据模型时,您应该忘记 UI、数据源或任何其他实现细节,而只是尝试创建一个反映应用程序的真实对象、条件或事件的模型处理。
其次,虽然数据模型处理实体如何相关,但它不处理为什么的逻辑 实体是相关的。该逻辑通常属于实体的自定义 NSManagedObject 子类的代码中。在这种情况下,实体关系的方式是MeetingNote 实体与Task 和Tags 相关。 为什么是任何特定的MeetingNote 对象和任何Task 对象之间应该存在关系,前提是MeetingNote 对象与@987654327 有关系@ 名称为task 的对象。
所以,您的基本数据模型应该如下所示:
MeetingNote{
title:string
date:date
tags<<-->>Tag.meetingNotes
tasks<-->>Task.meetingNote
}
Task{
name:string
meetingNote<<-->MeetingNote.tasks
}
Tag{
name:string
meetingNotes<<-->>MeetingNote.tags
}
现在问题变成了将自定义逻辑用于为什么的位置之一。逻辑上最简单的方法是为MeetingNote.tags 属性创建一个自定义访问器,检查添加或删除到MeetingNote instance 的标签名称是否等于task,如果是,则添加或删除Task 对象实例的MeetingNote.tasks 关系。
但是,这有一个明显的性能损失,即必须检查添加或删除的每个标签。更好的解决方案是将自定义添加到仅在 MeetingNote.tags.name' contains a value oftask 的确切条件下调用的一个点。
假设您有以下限制:
- 一个
MeetingNote 对象不能有一个相关的Task 对象而没有一个Tag object with name=="task"。
- 如果
MeetingNote 对象确实有一个Tag object with name=="task",它必须至少有一个相关的Task 对象。
- 如果
MeetingNote 对象失去了与Tag object with name=="task" 的关系,那么它就失去了所有的任务。
此时很明显,`Tag object with name=="task" 是一个特殊的对象,其行为不同于其他标签。这证明并要求它有自己的实体和子类,因此我们将添加到数据模型中:
TaskTag:Tag{
}
由于TaskTag 实体继承自Tag 实体,它可以自动继承Tag.meetingNotes 关系中的
然后在TaskTag NSManagedObject 子类中,我们将添加以下代码:
-(NSString *) name {
// the name of a TaskTag is always "task"
// you should set the defalut value in the data model to "task" as well.
return @"task";
}
-(void) setName:(NSString *)name{
return; // the name can never be changed
}
- (void)addMeetingNotesObject:(MeetingNote *)value {
NSSet *changedObjects = [[NSSet alloc] initWithObjects:&value count:1];
[self willChangeValueForKey:@"meetingNotes" withSetMutation:NSKeyValueUnionSetMutation usingObjects:changedObjects];
[[self primitiveValueForKey:@"meetingNotes"] addObject:value];
// If the meeting object does not an existing task, add one
if ([value.tasks count]==0 ) {
Task *t=[NSEntityDescription insertNewObjectForEntityForName:@"Task" inManagedObjectContext:self.managedObjectContext];
t.meetingNote=value;
}
[self didChangeValueForKey:@"meetingNotes" withSetMutation:NSKeyValueUnionSetMutation usingObjects:changedObjects];
[changedObjects release];
}
- (void)removeMeetingNotesObject:(MeetingNote *)value {
NSSet *changedObjects = [[NSSet alloc] initWithObjects:&value count:1];
[self willChangeValueForKey:@"meetingNotes" withSetMutation:NSKeyValueMinusSetMutation usingObjects:changedObjects];
[[self primitiveValueForKey:@"meetingNotes"] removeObject:value];
// A MeetingNote object cannot have any task without a taskTag so remove all task objects
if ([value.tasks count]!=0 ) {
[value removeTasks:value.tasks]; // removes all tasks from meeting notes
}
[self didChangeValueForKey:@"meetingNotes" withSetMutation:NSKeyValueMinusSetMutation usingObjects:changedObjects];
[changedObjects release];
}
- (void)addMeetingNotes:(NSSet *)value {
[self willChangeValueForKey:@"meetingNotes" withSetMutation:NSKeyValueUnionSetMutation usingObjects:value];
[[self primitiveValueForKey:@"meetingNotes"] unionSet:value];
Task *newTask;
// same as addMeetingNotesObject:
for (MeetingNote *meetNote in value) {
if ([meetNote.tasks count]==0 ) {
newTask=[NSEntityDescription insertNewObjectForEntityForName:@"Task" inManagedObjectContext:self.managedObjectContext];
newTask.meetingNote=value;
}
}
[self didChangeValueForKey:@"meetingNotes" withSetMutation:NSKeyValueUnionSetMutation usingObjects:value];
}
- (void)removeMeetingNotes:(NSSet *)value {
[self willChangeValueForKey:@"meetingNotes" withSetMutation:NSKeyValueMinusSetMutation usingObjects:value];
[[self primitiveValueForKey:@"meetingNotes"] minusSet:value];
//removeMeetingNotesObject:
for (MeetingNote *meetNote in value) {
[meetNote removeTasks:meetNote.tasks];
}
[self didChangeValueForKey:@"meetingNotes" withSetMutation:NSKeyValueMinusSetMutation usingObjects:value];
}
// Note: This code is not compiled and my contain errors.
此代码将自动强制执行上述约束,而无需执行任何其他操作。您还可以自定义Task 子类,以根据与其相关的MeetingNote 对象的某些属性自动设置其名称。
现在您已经了解了数据模型中的所有为什么逻辑,并且您的约束会自动执行。这可能不是您需要的确切解决方案,但您明白了。