【问题标题】:Reflect changes to objects in a relationship in parent object with NSFetchedResultsController使用 NSFetchedResultsController 反映对父对象关系中对象的更改
【发布时间】:2011-04-29 22:45:11
【问题描述】:

我有两个实体事件和时间。事件实体与时间实体具有一对多的关系,因为每个事件都可以执行多次。现在我想在 tableView 中按时间顺序显示所有事件。所以我设置了一个 fetchedResultsController 来获取所有时间对象,根据开始时间对它们进行排序,并通过与事件对象的关系显示事件信息。到目前为止,一切都很好。但是现在如果用户在表格中选择一个条目,我会将一个事件对象传递给可以编辑事件的 detailViewController。

问题是现在只有事件实体被标记为已更新。我通过查看 NSManagedObjectDidChange 通知的 userInfo 目录发现了这一点。因此,FRC 上的委托方法不会被触发,因为没有时间对象被更改。

如何手动将时间对象标记为已更改,以使 FRC 识别更改并相应地更新单元格?我尝试触发 KVO 方法 willChangeValueForKeydidChangeValueForKey,但到目前为止还没有成功。

非常感谢 托马斯

【问题讨论】:

  • 我现在尝试的是使用新的 userInfo 字典手动发布 NSManagedObjectContextObjectDidChangeNotifications,其中包含受事件对象更改影响的时间对象。不幸的是,FRC 没有反应。
  • 目前我正在解决一个问题,我想根据关系中的属性值对视图进行排序,而我的以下解决方案还不够。祝你好运! FRC 总是让人头疼。

标签: core-data nsfetchedresultscontroller


【解决方案1】:

我的模型略有不同,但可以轻松转换为您的模型。
我得到了一个树状结构:

  • 元素
    • 标题
    • 父母(一对一)
  • 文件夹:元素
    • 孩子(对多)
  • 文件:元素

添加或删除文件时,只有队列中的第一个文件夹会收到有关此更改的通知。当文件的标题更改时,不会通知单个文件夹。那么,该怎么办呢?
我尝试在我的 Element 类中覆盖 -willChangeValueForKey: 和 -didChangeValueForKey:。

- (void)willChangeValueForKey:(NSString *)key
{
    [super willChangeValueForKey:key];
    [self.parent willChangeValueForKey:@"children"];
}

- (void)didChangeValueForKey:(NSString *)key
{
    [super didChangeValueForKey:key];
    [self.parent didChangeValueForKey:@"children"];
}

基本上,它的作用是强制父文件夹更新,因为它的一个子文件夹发生了变化。
希望它也对你有用。

【讨论】:

  • 当我测试将其添加到我的应用程序时,这导致了一堆崩溃——使用风险自负。
  • FWIW:这似乎是正确的想法,但最好不要覆盖这些方法,而是在您对子对象进行更改的任何方法中调用它们,如下所示:
  • Apple 的文档明确指出“您不应在子类中覆盖此方法”。来自developer.apple.com/library/mac/documentation/Cocoa/Reference/…
  • 如上所述 - 重写这些方法不是一个好主意。我可以建议您使用类似但更安全的实现来更新您的答案吗?即将所有元素更新包装在一个更新方法中。
  • @JordanSmith 重写“setter”的全部意义在于不必担心调用其他方法来正确传播更改。此外,只有一个额外的“更新”方法不足以正确地以 will/did 对发送通知。
【解决方案2】:

我现在也在处理一些类似类型的更新。这是我解决问题的方法。

假设我们有对象 A,它与对象 B 相关。B 有一个属性 C。我们希望对属性 C 的更改反映在使用 A 作为获取对象的 FRC 中。我所做的是从对象 A 定义一个对属性 C 的访问器:

//A.m
- (void)setC:(int)cValue {
  [self willChangeValueForKey:@"b"];
  self.b.c = cValue
  [self didChangeValueForKey:@"b"];
}

- (int)c {
  return self.b.c;
}

这允许我的单元格根据类型为 NSFetchedResultsChangeUpdate 的 FRC 回调进行更新。希望这有助于解决您的问题。

【讨论】:

  • 我有点困惑。您在 A 中定义 B 的属性的设置器?您如何看待使用keyPathsForValuesAffectingValueForKey 设置依赖项?就像在这里完成cocoabuilder.com/archive/cocoa/…
  • B 显然可以设置它的属性,但为了方便起见,我也添加了一个属性来设置 A 的属性。在我的情况下,它有助于集中访问该属性,但对您来说可能完全不同。尽管如此,无论您在何处设置财产,您都应该能够使用遗嘱并进行更改。我认为这种设置依赖关系的方式是个好主意,但它在实践中对我来说并不奏效。
【解决方案3】:

@Jenox 的上述答案似乎是正确的想法,但最好不要覆盖这些方法,因为每当子对象上的 any 键发生更改时都会调用它们,并且可能会影响性能并引起意想不到的副作用(对我来说确实如此)。可能最好只用您对子对象进行更改的任何方法调用它们,如下所示:

- (void)updateFromDictionary:(NSDictionary *)aDictionary {
    [myParentModel willChangeValueForKey:@"myChildObject"];
    [super updateFromDictionary:aDictionary];
    [myParentModel didChangeValueForKey:@"myChildObject"];
}

注意updateFromDictionary是我的方法之一,不是系统方法。

【讨论】:

  • 这个世界肯定需要 Swift!
猜你喜欢
  • 1970-01-01
  • 2022-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-22
  • 2011-04-24
相关资源
最近更新 更多