核心数据获得值的总和.提取属性与传播

str*_*nge 5 iphone core-data objective-c fetched-property

我对Core Data相对较新(来自SQLite背景).刚读完"iOS的核心数据"一书,但当我开始为具有以下型号的应用程序建模时,我留下了一些令人困惑的问题:

  1. "帐户"实体,具有多对多的"交易"关系和"startingBalance"属性
  2. '交易'实体,具有多对多的"支付"关系(与账户相反)
  3. "付款"实体,其中包含实际"付款金额"的详细信息

出于性能原因,我想对模型进行去规范化,并在"帐户"实体中添加"TotalAmountSpent"属性(如本书所示),这样我就可以在发生变化时继续更新.

在实践中,这似乎很难通过Core Data实现.我无法弄清楚如何正确地做到这一点(并且不知道正确的方法是什么).所以我的问题是:

a)我应该将'TotalAmountSpent'更改为Fetched Property吗?是否有性能影响(我知道它是懒惰加载但我几乎肯定会为每个帐户获取该属性).如果我这样做,我需要能够在给定的时间段(例如最后三天)内获得花在'startingBalance'上的总金额.这在SQL中看起来很简单,但我如何在Core Data中执行此操作?我读过我可以使用@sum聚合函数但是如何使用@sum过滤'date'?我还读了数据中的任何变化都需要刷新fetched属性.我如何'倾听'改变?我是在"付款"实体的'willSave'方法中做到的吗?

b)每次将新的付款添加到交易时,我是否应该使用传播并手动更新"TotalAmountSpent"?最好的地方是什么?我应该在重写的NSManagedObject的'willSave'方法中做到吗?我担心,如果在帐户上更新了"startingBalance"字段,更新所有相应的交易/付款将是一场噩梦.然后我必须加载每笔付款并计算花费的总金额和帐户的最终余额.如果有数千笔付款可怕

任何关于此事的指导都将非常感激.谢谢!

Mar*_*rra 8

如果使用fetched属性,则无法在不首先将数据加载到内存中的情况下轻松查询该属性.因此,我建议您将实际的非规范化数据保留在实体中.

实际上有几种方法可以轻松地保持最新状态.

  1. 在你-awakeFromFetch/ -awakeFromInsert设置一个影响价值的关系的观察者.然后,当KVO(键值观察器)触发时,您可以进行计算并更新字段.学习KVC和KVO是一项宝贵的技能.

  2. 您可以-willSaveNSManagedObject子类中重写并对保存进行计算.虽然这更容易,但我不推荐它,因为它只会在保存时触发,并且无法保证您的帐户对象将被保存.

在任何一种情况下,您都可以使用KVC Collection Operators快速进行计算.通过集合运算符,您可以通过以下方式调用:

NSNumber *sum = [self valueForKeyPath:@"transactions.@sum.startingBalance"];
Run Code Online (Sandbox Code Playgroud)