0

我想清理一些瞬態屬性重新計算事件。在開發過程中,我幾乎對所有變化都進行了非常廣泛的更新。現在我正在嘗試確定最佳做法,檢查相關密鑰並根據需要進行更新。我的應用程序對象使用子和父屬性進行了數十次計算,其中單個更改可能導致許多級聯重新計算。NSManagedObjectContext不通知觀察者變化的瞬變

我以爲我理解的很好,指的是蘋果文檔here,並且我嘗試了在其他一些StackOverflow帖子上看到的模式,比如this @Marcus S. Zarra。我看到馬庫斯也發佈了關於這個主題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; 
} 

我想這是直接從文檔的使用情況,但我的觀察沒有得到通知的變化來worksheetTotal。

當對lineItem進行更改時,會收到該通知並在此處調用updateWorksheetTotal。我希望這會觸發另一個通知,即工作表總計現在已更改的上下文,但事實並非如此。我已經嘗試了許多變體和我已經看到的代碼組合,但我沒有做任何事情似乎使NSManagedObjectContext認爲我的更新爲worksheetTotal是值得向觀察員報告的變化。

缺少什麼我在這裏?

以下是用於監聽父對象更改的相關代碼。

- (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

你的觀察者如何傾聽這種變化? –

+0

@JesseRusak我在 –

回答

2

文檔對於changedValues法說:

此方法僅報告說,被定義爲接收器的 持久屬性,不改變瞬態 屬性或自定義實例變量屬性的變化。此方法不會不必要地激發關係錯誤。

由於您的財產是短暫的,它不會出現在那裏。我建議使用KVO來監視這些屬性的變化。

+0

Doh!我應該看看changedValues的文檔。這從來沒有發生過。我確實相信它。我嘗試了無數的配置來強制那個吸盤在那裏。學到了很多。我不想放棄使用觀察環境而不是單獨的KVO。有太多這些要保留。我將嘗試添加一個可以報告並在需要重新計算時設置的標誌。謝謝傑西。 –

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) { 
+0

這個問題上增加了一個例子,謝謝,我修改過,似乎沒有什麼區別。 –

+0

對您的代碼有更多建議。試一下。 – Saran