CoreData:如何刷新“计算”属性?

时间:2013-12-28 23:17:43

标签: core-data

我的NSFetchedResultsController工作得很好,只要“基本”属性得到改变。但是,如果我有一个计算的标签,并且我在导航控制器堆栈上的另一个视图控制器中更改了影响此标签的某些属性,则此标签不会更新。

例如,我的标签应显示实体SpendingCategory中保存的预算位置金额。

self.budgetLeftLabel.text = [NSString stringWithFormat:@"%@ %@", [[self.spendingCategory getExpendituresAmount] getLocalizedCurrencyStringWithDigits:0], NSLocalizedString(@"left", nil)];

我使用此方法从SpendingCategory上的类别中获取此值:

- (NSNumber *)getExpendituresAmount
{
    return [self.hasExpenditures valueForKeyPath:@"@sum.amount"];
}

但是这个标签没有得到NSFetchedResultsController的任何更新。我的应用程序中有几个位置,因为计算了值,所以不会发生这种情况。我需要做些什么来改变这些更新?

使用数据结构进行编辑: 好的,我的支出类别数据结构大致(预算):

name (string)
cost (double)
position (integer 16)
Relationsships: hasExpenditures

我的支出结构(用于跟踪):

amount (double)
date (Date)
description (string)
Relationsships: forSpendingCategory

我希望现在更清楚了。那么为什么这些值不会更新呢?

2 个答案:

答案 0 :(得分:1)

当相关NSFetchedResultsController实例中的属性更新时,NSManagedObject会被发现。如果您要更改纯粹计算的内容,则更新永远不会触发。为什么这有关系?

如果您要更改支出实体中的某些内容(顺便说一下,实体名称应该是单数),而您正在查看支出类别实体,那么NSFetchedResultsController会因为您没有开火而被解雇改变任何相关的东西。

如何解决这个问题?

取决于。我通常在实体中保留派生的值并保留它。此外,每当孩子改变相关值时,我都会重新计算父级。这将导致NSFetchedResultsController触发。

你如何看待价值观?

要么让孩子在父母(icky)上调用方法,要么父母通过KVO(更好)监视子女的值。您的个人偏好决定于此。

更新1

要在实体中保留派生值,您需要向实体添加新属性并存储它。关于属性没有什么特别之处。有助于记住核心数据不是数据库。核心数据是您的数据模型,如果您愿意,它会一直存在于数据库中。因此,在这种情况下,您希望非规范化数据库。

当我正在寻找一个观看孩子的好链接时,我偶然发现了这个例子。

KVO object properties within to-many relationship

虽然接受的答案不是很好,但使用NSFetchedResultsController的第二个答案非常有趣,值得探讨。基本思想是您的父对象在NSFetchedResultsController-awakeFromFetch上实例化-awakeFromInsert,当它触发时,它们会重新计算派生值。因此,该值始终是最新的,并且基于视图控制器的NSFetchedResultController实例将触发,因为父对象已更改。

答案 1 :(得分:0)

我之前做过类似的事情,基本上你需要将计算出的值存储在CoreData模型的瞬态属性中,而不是实现自己的setter和getter。然后在相关的NSManagedObject中,您需要实现两个方法:

// this will populate the values when 
// the entity is retrieved from the store
-(void)awakeFromFetch {
  [self refreshCellInfo];
}

// this will refresh the values when
// the object goes to fault
// (for example when it is off screen)
-(void)willTurnIntoFault {
  [self refreshCellInfo];
}

-(void)refreshCellInfo {
  // update all your derived values...
}