【问题标题】: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 文档?万一你错过了它,它说:你不能覆盖这个方法

标签: ios core-data


【解决方案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 }
}

【讨论】:

    猜你喜欢
    • 2015-07-31
    • 1970-01-01
    • 1970-01-01
    • 2017-03-20
    • 2019-04-05
    • 2013-09-04
    • 2012-07-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多