【问题标题】:Notify parent Entity when child Relationship Entity changes in Core Data当核心数据中的子关系实体发生变化时通知父实体
【发布时间】:2011-10-11 18:26:15
【问题描述】:

当它的任何一个关系对象发生变化时,是否可以在父实体中接收回调或通知?当实体的属性发生变化时,这很有效。下面的方法...

- (void)didChangeValueForKey:(NSString *)key

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

我要做的是在父实体的任何一个属性或关系对象发生更改时更新它的 timeStamp 属性。

【问题讨论】:

    标签: ios core-data entity-relationship


    【解决方案1】:

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

    监视特定的子实体要复杂得多。有几种方法可以解决它:

    1. 当其属性发生变化时,让子代 ping 父代。
    2. 让父级监听 NSManagedObjectContextDidSaveNotification 并查看其子级是否在该存档中
    3. 让家长观察孩子的价值观。

    可能还有其他解决方案,但我推荐的三个解决方案是 #2。它很容易设置,而且对性能的影响非常小。

    【讨论】:

    • 我喜欢我可以将问题发送到虚空并收到回复!我决定解决方案#2。我正在遍历父关系并检查是否有任何关系 managedObjects 与通知 managedObject 相同。
    • 请记住,您可以针对返回的NSSet 实例运行谓词。无需循环 :) 谓词可以是 @"entity.name == %@ && parent == %@" 之类的东西,它将返回当前实体的任何子实体,这些子实体属于您关心的关系。
    • 太棒了,谢谢!奇迹般有效。我希望您不介意我是否包含指向您有关此主题的博客文章的链接"Parent Watching it's Child" 以及您的书的插件"Core Data" 我经常引用它。此外,在我的情况下,我需要做的另一件事是为 NSManagedObject 子类中的时间戳创建原始访问器,以防止它进入无限通知循环。
    • 没问题,很高兴有帮助!
    • @SAHM 选项 2 和 3 更好。对于选项 1,您可以在重写的 setter(或 Swift 中的 didSet)中执行此操作
    【解决方案2】:

    在另一个答案中,我发现 1,2 和 3 效率太低。特别是 2 和“父母看着它的孩子”博客文章中的示例。我的问题是每个父母都必须响应上下文通知,如果是孩子,基本上每个对象都会被保存(不要介意 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]}];;
    }
    

    要更新父时间戳,我一直在使用的以下简洁解决方案 (second last post) 可能会有所帮助,例如在父级使用:

    - (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];
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多