核心数据:检测孩子何时被删除

Posted

技术标签:

【中文标题】核心数据:检测孩子何时被删除【英文标题】:Core data: detect when child has been deleted 【发布时间】:2015-11-09 16:10:12 【问题描述】:

在我的应用中,我有一个Result 实体,它可以包含多个Expense 实体。

每个Expense 都有一个金额,我的Result 包含费用的总和。

当添加或删除 Expense 时,我需要自动计算该总和。

当我的Expense被添加时,我已经成功地做到了这一点,从ExpenseNSManagedObject覆盖didChangeValueForKey。但是,即使在删除生效时调用该方法,对Result 对象的引用也为零。我有一个想法使用willChangeValueForKey 来存储我的Result 对象的引用,但我觉得这很脏。

您是否有更好的主意,以便 Result 对象在其子对象之一被删除时得到通知?

【问题讨论】:

为 Result 创建 NSFetchedResutsController 怎么样,每次其中的某些内容发生变化时,控制器都会告诉你 您是否阅读了 didChangeValueForKey:NSManagedObject 文档?万一你错过了它,它说:你不能覆盖这个方法 【参考方案1】:

我建议你像这样听 NSManagedObjectContextObjectsDidChangeNotification:

 [[NSNotificationCenter defaultCenter] 
  addObserver:self 
     selector:@selector(dataModelHasChanged:) 
         name:NSManagedObjectContextObjectsDidChangeNotification 
       object:managedObjectContext];

每次发生变化时,您都可以通过这种方式检测到:

- (void)dataModelHasChanged:(NSNotification *)notification

    NSSet *updatedObjects = [[notification userInfo] objectForKey:NSUpdatedObjectsKey];
    NSSet *deletedObjects = [[notification userInfo] objectForKey:NSDeletedObjectsKey];
    NSSet *insertedObjects = [[notification userInfo] objectForKey:NSInsertedObjectsKey];

// Do something in response to this

【讨论】:

这很好,但我将结果存储回 Result 对象,这将导致无限循环 为什么会导致死循环?只需检测它是否被删除/插入,然后相应地扣除/添加总和 没有无限循环,但您缺少用户信息键。而且,这只在用户事件之后更新值(即,待处理的更改已被处理)。如果要进行主动缓存管理,还需要考虑其他边缘情况。一些最明显的:你会一直做计算吗?如果没有,你将如何决定?处理有缺陷的对象怎么办?您是要触发故障以获取数据,还是将其缓存?如果你缓存它,你会怎么做?等等等等……缓存管理很难。 如果我检查被删除的费用,我无权访问 Result 对象,因为它已经为零。如果我检查正在修改的结果,然后计算总和并修改它,它将导致无限循环。如果您对此有任何想法,我很乐意接受! 因此,每次您删除一个费用时,此方法都会调用两次:一次用于结果,一次用于费用。对吗?【参考方案2】:

在我看来,Result 中的总和应该是一个计算属性。将总和存储在数据库中似乎是多余的。

请注意,使用 KVC 会非常高效:

let sum = self.expenses.valueForKeyPath("@sum.amount")

【讨论】:

有大量计算要做,因为我稍后会计算结果和其他统计数据的总和,我需要尽可能多地进行预计算。 您会惊讶于 Core Data 能以多快的速度进行此类计算。我已经建立了一个非常复杂的分析模型,它实际上在这种模式下表现得非常好,甚至包括涉及函数和递归的更复杂的计算。【参考方案3】:

或者,您可以将计算属性添加到 Expenses 并在那里管理所需的副作用。

@NSManaged private var storedAmount: NSNumber

var amount: NSNumber 
   set  
      amount = newValue
      storedAmount = amount
      // do your computation and update Result
   
   get   return storedAmount 

【讨论】:

以上是关于核心数据:检测孩子何时被删除的主要内容,如果未能解决你的问题,请参考以下文章

检测节点何时被删除(或因为父节点被从 DOM 中删除)

如何检测新对象何时被生成或从统一中删除以获得评分/分数?

有没有办法检测 DOM 节点何时要从 DOM 中删除?

Phaser 2 - 如何检测我何时拖动另一个精灵?

如何检测用户何时从 Facebook 删除应用

JSFL:检测元素何时被翻转