当核心数据中的子关系实体发生更改时通知父实体

发布于 2024-12-09 01:56:23 字数 233 浏览 5 评论 0原文

当其关系对象发生更改时,是否可以在父实体中接收回调或通知?当实体的属性发生变化时,这非常有用。以下方法...

- (void)didChangeValueForKey:(NSString *)key

在我的 Entity 子类上调用。但是,当其中一个关系中的属性发生更改时,不会调用此方法。

我想要做的是,当父实体的任何一个属性或关系对象发生更改时,更新父实体上的时间戳属性。

Is it possible to receive a callback or notification in the parent Entity when any one it's relationship objects changes? This works great when an attribute of the Entity changes. The following method...

- (void)didChangeValueForKey:(NSString *)key

is invoked on my Entity subclass. However this method is not invoked when an attribute in one of the relationships changes.

What I'm trying to do is update the timeStamp attribute on my parent Entity when any one of its attributes or relationship objects changes.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

再见回来 2024-12-16 01:56:23

父实体可以将自己设置为关系的观察者,并且当该关系发生变化时它将收到通知。但是,只有在实际关系(添加或删除子项)发生时才会触发。

监视特定的子实体要困难得多。有几种方法可以解决这个问题:

  1. 当子进程的属性发生变化时,让子进程对父进程执行 ping 操作。
  2. 让父级侦听 NSManagedObjectContextDidSaveNotification 并查看其子级是否在该保存中
  3. 让父级观察子级的值。

可能还有其他解决方案,但在这三个解决方案中我推荐#2。它的设置非常简单,并且对性能的影响非常小。

The parent entity can set itself as an observer of the relationship and it will get notified when that relationship changes. However that will only be fired when the actual relationship (adding or removing a child) occurs.

To watch for a specific child entity is far more tricky. There are a couple of ways to go about it:

  1. Have the child ping the parent when its properties change.
  2. Have the parent listen for NSManagedObjectContextDidSaveNotification and look to see if any of its children are in that save
  3. Have the parent observe the values on the children.

There may be other solutions but of the three I recommend #2. It is pretty easy to set up and the performance impact is pretty minimal.

梦里梦着梦中梦 2024-12-16 01:56:23

在另一个答案中,我发现 1,2 和 3 效率太低。特别是 2 以及“Parent Watching it's Child”博客文章中的示例。我的问题是,每个父对象都必须响应上下文通知,并且基本上每个对象都被保存(如果它是子对象)(不用介意 ContextDidSave 在这种情况下更合适!)。相反,我会提出选项 4:

  1. 让子级覆盖 didSave 并广播包含父级的 NSManagedObjectContextDidSaveNotification。

我的解决方案更加高效,并且对我来说更加面向对象,因为正在更改的对象正在响应其自身的更改。要实现这一点,在子对象中使用:

-(void)didSave{
    [super didSave];
    // notify that the parent has changed.
    [[NSNotificationCenter defaultCenter] postNotificationName:NSManagedObjectContextObjectsDidChangeNotification
                                                        object:self.managedObjectContext
                                                      userInfo:@{NSUpdatedObjectsKey : [NSSet setWithObject:self.parent]}];;
}

要更新父时间戳,可以使用以下简洁的解决方案(倒数第二篇文章)我一直在使用可能会有所帮助,例如在父级使用中:

- (void) awakeFromInsert
{
    [super awakeFromInsert];
    // set the default dates
    NSDate* date = [NSDate date];
    self.timestamp = date;
    //allow any future modifications to change the timestamp
    _finishedStartup = YES;
}

- (void) awakeFromFetch
{
    [super awakeFromFetch];
    // we should already have creation and modified dates.
    _finishedStartup = YES;
}

- (void) didChangeValueForKey: (NSString *) thisKey
{
    [super didChangeValueForKey: thisKey];

    if(![thisKey isEqualToString:@"timestamp"] && // prevent infinite loop
       ![self isFault] &&
       ![[[self managedObjectContext] undoManager] isUndoing] &&
       _finishedStartup) // ensures we arent being called by the object being loaded from fetched data.
    {
        self.timestamp = [NSDate date];
    }
}

In the other answer I found 1,2 and 3 too inefficient. Particularly 2 and the example in the "Parent Watching it's Child" blog post. My issue with that is every single parent had to respond to the context notification and essentially every object being saved if it is the child (never mind the fact ContextDidSave is more appropriate in that case!). Instead, I would propose an option 4:

  1. Have the child override didSave and broadcast a NSManagedObjectContextDidSaveNotification containing the parent.

My solution is more efficient and feels more object-oriented to me since the object that is changing is responding to its own change. To implement this, within the child object use:

-(void)didSave{
    [super didSave];
    // notify that the parent has changed.
    [[NSNotificationCenter defaultCenter] postNotificationName:NSManagedObjectContextObjectsDidChangeNotification
                                                        object:self.managedObjectContext
                                                      userInfo:@{NSUpdatedObjectsKey : [NSSet setWithObject:self.parent]}];;
}

To update the parent timestamp, the following neat solution (second last post) I've been using might help, e.g. in the parent use:

- (void) awakeFromInsert
{
    [super awakeFromInsert];
    // set the default dates
    NSDate* date = [NSDate date];
    self.timestamp = date;
    //allow any future modifications to change the timestamp
    _finishedStartup = YES;
}

- (void) awakeFromFetch
{
    [super awakeFromFetch];
    // we should already have creation and modified dates.
    _finishedStartup = YES;
}

- (void) didChangeValueForKey: (NSString *) thisKey
{
    [super didChangeValueForKey: thisKey];

    if(![thisKey isEqualToString:@"timestamp"] && // prevent infinite loop
       ![self isFault] &&
       ![[[self managedObjectContext] undoManager] isUndoing] &&
       _finishedStartup) // ensures we arent being called by the object being loaded from fetched data.
    {
        self.timestamp = [NSDate date];
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文