我正在尝试清理一些瞬态属性重新计算事件。在开发过程中,我刚刚对几乎所有的更改进行了非常广泛的更新。现在我正在尝试确定最佳实践,检查相关密钥并根据需要进行更新。我的应用程序对象使用子属性和父属性加载了许多计算,其中单个更改可能导致许多级联重新计算。
我认为我理解得很好,指的是Apple文档here,我已经尝试了@Marcus S. Zarra在其他一些StackOverflow帖子上看到的模式,例如this。我看到马库斯还发表了一篇关于这个主题的文章here。
我现在所拥有的是:
#pragma mark _ worksheetTotal (transient)
+(NSSet *)keyPathsForValuesAffectingWorksheetTotal
{
// local, non-transient, dependent keys here
return [NSSet setWithObjects:@"dailySustenance", nil];
}
-(void)updateWorksheetTotal
{
NSDecimalNumber *lineItemTotal = [self.items valueForKeyPath:@"@sum.lineHoursCost"];
NSDecimalNumber *total = [lineItemTotal decimalNumberByAdding:self.dailySustenance];
[self setWorksheetTotal:total];
}
-(void)setWorksheetTotal:(NSDecimalNumber *)newWorksheetTotal
{
if ([self worksheetTotal] != newWorksheetTotal) {
[self willChangeValueForKey:@"worksheetTotal"];
[self setPrimitiveWorksheetTotal:newWorksheetTotal];
[self didChangeValueForKey:@"worksheetTotal"];
}
}
-(NSDecimalNumber *)worksheetTotal
{
[self willAccessValueForKey:@"worksheetTotal"];
NSDecimalNumber *result = [self primitiveWorksheetTotal];
[self didAccessValueForKey:@"worksheetTotal"];
return result;
}
我认为这直接来自文档用例,但我的观察员没有收到有关workheetTotal更改的通知。
当对lineItem进行更改时,会收到该通知,并在此处调用响应updateWorksheetTotal
。我希望这会触发workheetTotal现在已经改变的上下文的另一个通知,但事实并非如此。我尝试了很多我见过的代码变体和组合,但我做的任何事情似乎都没有让NSManagedObjectContext
认为我对worksheetTotal
的更新是值得向观察者报告的更改。
我在这里缺少什么?
以下是监听Parent对象更改的相关代码。
- (void) objectContextDidChange: (NSNotification *) notification
{
NSSet *updatedObjects = [[notification userInfo] objectForKey:NSUpdatedObjectsKey];
// Next look for changes to worksheet that may affect our calculated fields
NSPredicate *worksheetPredicate = [NSPredicate predicateWithFormat:@"entity.name == %@ && estimate == %@", @"LaborWorksheet", self];
NSPredicate *materialsPredicate = [NSPredicate predicateWithFormat:@"entity.name == %@ && estimate == %@", @"MaterialLineItems", self];
NSPredicate *combinedPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:[NSArray arrayWithObjects:worksheetPredicate, materialsPredicate, nil]];
NSSet *myWorksheets = [updatedObjects filteredSetUsingPredicate:combinedPredicate];
// These are the relevant keys in this estimates labor and materials worksheet
NSSet *relevantKeys = [NSSet setWithObjects:@"worksheetTotal", @"totalEquipmentcost", nil];
BOOL clearCache = NO;
if (myWorksheets.count != 0) {
for (NSManagedObject *worksheet in myWorksheets) {
NSLog(@"got some");
// Here is where it fails, worksheetTotal is not in changedValues.allKeys. It is an empty set.
// Not sure how that could be when I got it from updatedObjects set of userInfo. How could it have no changed values?
NSSet *changedKeys = [NSSet setWithArray:worksheet.changedValues.allKeys];
if ([changedKeys intersectsSet:relevantKeys]) {
clearCache = YES;
NSLog(@"found some, set to clear cache");
// no need to continue checking
break;
}
}
}
if (clearCache) {
// I would update dependent keys here but it is never reached
}
}
答案 0 :(得分:2)
changedValues
方法的文档说:
此方法仅报告对定义为的属性的更改 接收器的持久属性,而不是瞬态变化 属性或自定义实例变量。这种方法没有 不必要的火灾关系错误。
由于您的财产是短暂的,它不会出现在那里。我建议使用KVO来监控这些属性的变化。
答案 1 :(得分:1)
您在didAccessValueForKey之前返回。存储到变量并在didAccessValueForKey之后返回它,如
-(NSDecimalNumber *)worksheetTotal
{
[self willAccessValueForKey:@"worksheetTotal"];
NSDecimalNumber *yourVariable = [self primitiveWorksheetTotal];
[self didAccessValueForKey:@"worksheetTotal"];
return yourVariable;
}
我希望它有效。
修改强>
在
-(void)setWorksheetTotal:(NSDecimalNumber *)newWorksheetTotal
考虑改变
if ([self worksheetTotal] != newWorksheetTotal) {
到
if (worksheetTotal != newWorksheetTotal) {