当项目添加到核心数据 NSManagedObject 关系的 NSSet 或从中删除时如何触发通知?

How to trigger notifications when item added to or removed from Core Data NSManagedObject relationship's NSSet?

每当在自定义 NSManagedObject 子类中的一对多关系/NSSet 中添加或删除项目时,触发 NSNotification 的正确方法是什么?

我有一个自定义 NSManagedObject 子类,它与另一个 NSManagedObject 子类具有一对多的无序关系。为了清楚起见,假设这两个子类是 TeacherStudent,其中一个 Teacher 可以有多个 Student 对象,但每个 Student 只分配给一个Teacher.

我希望能够在将 Student 添加到 Teacher 或从中删除时触发通知,无论是因为 Student 只是分配给或从Teacher 还是因为 Student 已从 Core Data 中完全删除。

我试过使用 KVO,但你似乎无法 将观察者添加到 NSSetcount 属性将观察者添加到 @dynamic 属性。此外,我尝试实现自己自定义的对多访问器方法,如 Apple's documentation 中所述,但在测试中,我的自定义访问器方法似乎从未被调用过。万一我的实现有问题,这里是我在 Teacher:

中的实现方式
@implementation Teacher

@dynamic students;

- (void)addStudentsObject:(Student *)value
{
    NSSet *changedObjects = [[NSSet alloc] initWithObjects:&value count:1];
    [self willChangeValueForKey:NSStringFromSelector(@selector(students))
                withSetMutation:NSKeyValueUnionSetMutation
                   usingObjects:changedObjects];
    [[self primitiveStudents] addObject:value];
    [self didChangeValueForKey:NSStringFromSelector(@selector(students))
               withSetMutation:NSKeyValueUnionSetMutation
                  usingObjects:changedObjects];
    [[NSNotificationCenter defaultCenter] postNotificationName:NOTIFICATION_TEACHER_STUDENT_WAS_ADDED object:self];
}

- (void)removeStudentsObject:(Student *)value
{
    NSSet *changedObjects = [[NSSet alloc] initWithObjects:&value count:1];
    [self willChangeValueForKey:NSStringFromSelector(@selector(students))
                withSetMutation:NSKeyValueMinusSetMutation
                   usingObjects:changedObjects];
    [[self primitiveStudents] removeObject:value];
    [self didChangeValueForKey:NSStringFromSelector(@selector(students))
               withSetMutation:NSKeyValueMinusSetMutation
                  usingObjects:changedObjects];
    [[NSNotificationCenter defaultCenter] postNotificationName:NOTIFICATION_TEACHER_STUDENT_WAS_REMOVED object:self];
}

- (void)addStudents:(NSSet *)values
{
    [self willChangeValueForKey:NSStringFromSelector(@selector(students))
                withSetMutation:NSKeyValueUnionSetMutation
                   usingObjects:values];
    [[self primitiveStudents] unionSet:values];
    [self didChangeValueForKey:NSStringFromSelector(@selector(students))
               withSetMutation:NSKeyValueUnionSetMutation
                  usingObjects:values];
    [[NSNotificationCenter defaultCenter] postNotificationName:NOTIFICATION_TEACHER_STUDENTS_WERE_ADDED object:self];
}

- (void)removeStudents:(NSSet *)values
{
    [self willChangeValueForKey:NSStringFromSelector(@selector(students))
                withSetMutation:NSKeyValueMinusSetMutation
                   usingObjects:values];
    [[self primitiveStudents] minusSet:values];
    [self didChangeValueForKey:NSStringFromSelector(@selector(students))
               withSetMutation:NSKeyValueMinusSetMutation
                  usingObjects:values];
    [[NSNotificationCenter defaultCenter] postNotificationName:NOTIFICATION_TEACHER_STUDENTS_WERE_REMOVED object:self];
}

...

@end

事实证明,根本问题是您用作参考的 Apple Docs 中的奇特访问器示例实际上不是 all 关系的访问器.它们是您可以根据需要实现的额外便利访问器。但是因为您试图通过覆盖所有 setters(或任何您想要调用的可变访问器)来插入代码,所以您还需要覆盖最基本的 setter.

对多关系的最基本访问器是 setters 和整个关系的 NSSet 对象的 getter。在您的情况下,- (NSSet*) students- (void) setStudents:(NSSet*)students.

因此,您的通知至少需要发布在 setStudents:

-(void) setStudents:(NSSet*)students{ 
    [self willChangeValueForKey:@"students"]; 
    [self setPrimitiveValue:students forKey:@"students"]; 
    [self didChangeValueForKey:@"students"]; 
    [[NSNotificationCenter defaultCenter] postNotificationName:NOTIFICATION_TEACHER_STUDENTS_WERE_ADDED object:self];

} 

那个是默认使用的setter。