当项目添加到核心数据 NSManagedObject 关系的 NSSet 或从中删除时如何触发通知?
How to trigger notifications when item added to or removed from Core Data NSManagedObject relationship's NSSet?
每当在自定义 NSManagedObject
子类中的一对多关系/NSSet
中添加或删除项目时,触发 NSNotification
的正确方法是什么?
我有一个自定义 NSManagedObject
子类,它与另一个 NSManagedObject
子类具有一对多的无序关系。为了清楚起见,假设这两个子类是 Teacher
和 Student
,其中一个 Teacher
可以有多个 Student
对象,但每个 Student
只分配给一个Teacher
.
我希望能够在将 Student
添加到 Teacher
或从中删除时触发通知,无论是因为 Student
只是分配给或从Teacher
还是因为 Student
已从 Core Data 中完全删除。
我试过使用 KVO,但你似乎无法 将观察者添加到 NSSet
的 count
属性将观察者添加到 @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。
每当在自定义 NSManagedObject
子类中的一对多关系/NSSet
中添加或删除项目时,触发 NSNotification
的正确方法是什么?
我有一个自定义 NSManagedObject
子类,它与另一个 NSManagedObject
子类具有一对多的无序关系。为了清楚起见,假设这两个子类是 Teacher
和 Student
,其中一个 Teacher
可以有多个 Student
对象,但每个 Student
只分配给一个Teacher
.
我希望能够在将 Student
添加到 Teacher
或从中删除时触发通知,无论是因为 Student
只是分配给或从Teacher
还是因为 Student
已从 Core Data 中完全删除。
我试过使用 KVO,但你似乎无法 将观察者添加到 将观察者添加到 NSSet
的 count
属性@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。