简体   繁体   English

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

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

What is the correct way to trigger an NSNotification whenever an item is added to or removed from a to-many relationship / NSSet within a custom NSManagedObject subclass? 每当将项目添加到自定义NSManagedObject子类中的多对多关系/ NSSet或从中删除项时,触发NSNotification的正确方法是什么?

I have a custom NSManagedObject subclass that has a one-to-many unordered relationship to another NSManagedObject subclass. 我有一个自定义NSManagedObject子类,该子类与另一个NSManagedObject子类具有一对多的无序关系。 For clarity, let's say these two subclasses are Teacher and Student , where one Teacher can have multiple Student objects but where each Student is only assigned to one Teacher . 为了清楚起见,假设这两个子类是TeacherStudent ,其中一个Teacher可以具有多个Student对象,但是每个Student只分配给一个Teacher

I'd like to be able to trigger a notification whenever a Student is added to or removed from a Teacher , whether because Student was simply assigned to or from a Teacher or whether because Student was deleted entirely from Core Data. 我希望每当将Student添加到Teacher或从中删除Student都可以触发通知,无论是因为仅将Student分配给Teacher还是从Teacher分配Student ,或者是因为从核心数据中完全删除了Student

I tried using KVO but it doesn't seem like you can 我尝试使用KVO,但似乎无法 add an observer to an NSSet 's count property NSSetcount属性添加观察者 add an observer to a @dynamic property. 将观察者添加到@dynamic属性。 Additionally, I tried implementing my own custom to-many accessor method as outlined in Apple's documentation , but in testing it seems like my custom accessor methods are never called. 此外,我尝试实现苹果文档中概述的自己的自定义“一对多”访问器方法,但在测试中似乎从未调用过我的自定义访问器方法。 In case there is something wrong with my implementation, here is how I implemented it within Teacher : 如果我的实现出现问题,这是我在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

The fundamental issue turns out to be that the fancy accessor examples in the Apple Docs that you were using as a reference are actually not all the accessors for the relationship. 根本的问题是,您用作参考的Apple Docs中精美的访问器示例实际上并不是该关系的所有访问器。 They are extra convenience accessors that you can implement if you want. 它们是您可以实现的额外的便捷访问器。 But because you are trying to insert your code by overriding all the setters (or whatever you want to call mutating accessors), you need to also override the most basic setter. 但是,因为您试图通过覆盖所有设置器(或任何您想要调用变异访问器的方法)来插入代码,所以您还需要覆盖最基本的设置器。

The most basic accessors for a to-many relationship are setters and getters for the NSSet object for the entire relationship. 一对多关系的最基本访问器是整个关系的NSSet对象的设置器和获取器。 In your case, - (NSSet*) students and - (void) setStudents:(NSSet*)students . 在您的情况下, - (NSSet*) students- (void) setStudents:(NSSet*)students

So, at a minimum, your notification needs to be posted in setStudents : 因此,至少,您的通知需要发布在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];

} 

That is the setter being used by default. 是默认情况下使用的setter。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM