0

Я пытаюсь очистить некоторые события перераспределения свойств переходных процессов. В разработке я только что использовал очень широкий ход обновления практически для всех изменений. Теперь я пытаюсь определить наилучшую практику, проверять соответствующие ключи и обновлять как можно меньше. Мои объекты приложения загружаются десятками вычислений с использованием дочерних и родительских атрибутов, где одно изменение может привести к каскадным перерасчетам.NSManagedObjectContext не уведомляет наблюдателя об изменениях для переходных процессов

Я думал, что понял довольно хорошо, ссылаясь на документацию Apple here, и я экспериментировал с шаблонами, замеченными на некоторых других сообщениях StackOverflow, таких как this один by @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.

При внесении изменений в строкуItem это уведомление получено и отвечает updateWorksheetTotal. Я ожидаю, что это приведет к еще одному уведомлению в контексте, что рабочий листTotal теперь изменился, но это не так. Я пробовал множество вариаций и комбинаций кода, который я видел, но ничего не делает, что делает 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! Я должен был посмотреть на документацию измененных значений. Это мне никогда не приходило в голову. Я действительно этому верю. Я попробовал бесчисленные конфигурации, чтобы заставить там присоску. Учился много. Я не хочу отказаться от использования наблюдения за контекстом, а не для отдельного КВО. Их слишком много. Я попытаюсь добавить флаг, который сообщает и устанавливает это, когда требуется пересчет. Спасибо Джесси. –

1

Вы возвращаетесь до didAccessValueForKey. Сохраните переменную и верните ее после didAccessValueForKey, например

-(NSDecimalNumber *)worksheetTotal 
{ 
    [self willAccessValueForKey:@"worksheetTotal"]; 
    NSDecimalNumber *yourVariable = [self primitiveWorksheetTotal]; 
    [self didAccessValueForKey:@"worksheetTotal"]; 
    return yourVariable; 
} 

Надеюсь, что это сработает.

Edit:

В

-(void)setWorksheetTotal:(NSDecimalNumber *)newWorksheetTotal 

рассмотреть вопрос об изменении

if ([self worksheetTotal] != newWorksheetTotal) { 

в

if (worksheetTotal != newWorksheetTotal) { 
+0

Спасибо, я изменил и, похоже, ничего не изменил. –

+0

еще одно предложение вашего кода. Попробуй. – Saran

Смежные вопросы