Question

J'ai donc deux objets, Invoice et InvoiceLineItem. InvoiceLineItem a une propriété appelée cost et elle est créée dynamiquement en fonction d'autres propriétés. Pour aider avec les liaisons KVO / I que j'utilise:

+ (NSSet *)keyPathsForValuesAffectingCost {
    return [NSSet setWithObjects:@"lineItemType", @"serviceCost", @"hourlyRate", @"timeInSeconds", @"productCost", @"quantityOfProduct", @"mileageCost", @"milesTraveled", nil];
}

Cela fonctionne très bien. Lorsque je modifie une propriété telle que serivceCost, le coût principal dans les mises à jour de la vue tableau est correct.

Dans l'objet Facture, j'ai un NSMutableArray de InvoiceLineItems. La facture a une propriété similaire appelée totalCost. Il est calculé en effectuant une itération sur les éléments de campagne et tant que ce dernier n'est pas marqué comme supprimé (ce que je fais pour des raisons de synchronisation), il ajoute les coûts et crée le totalCost.

Maintenant ma question / problème. Comment configurer le totalCost de Invoice pour qu'il fonctionne avec les liaisons KVO / bind lorsque l'un des coûts de l'élément de ligne a changé?

J'ai essayé de configurer:

+ (NSSet *)keyPathsForValuesAffectingTotalCost {
    return [NSSet setWithObjects:@"lineItems.cost", nil];
}

mais ça ne marche pas. Je me retrouve avec une erreur dans la console: [<NSCFArray 0x1499ff40> addObserver:forKeyPath:options:context:] is not supported. Key path: cost

Était-ce utile?

La solution

Je ne crois pas que beaucoup de relations soient prises en charge pour la propagation automatique de KVO. La documentation ne dit pas explicitement d'une manière ou d'une autre, mais d'après ce que je sais du KVO en général, observer les sous-clés d'une relation à plusieurs tend à ne pas être trivial.

Pour y remédier, il serait utile d’observer manuellement la propriété cost de chaque objet InvoiceLineItem, en implémentant plusieurs accesseurs KVC pour la propriété lineItems de la classe Invoice lors d’un appel addObserver / removeObserver. méthodes d'insertion / suppression, respectivement, puis déclenchez la totalCost modification manuellement à l'aide de willChangeValueForKey: / didChangeValueForKey :. Donc, quelque chose comme ceci (code grossièrement esquissé, disclaimers, etc.):

- (void)insertObject:(InvoiceLineItem*)newItem inLineItemsAtIndex:(unsigned)index
{
    [newItem addObserver:newItem forKeyPath:@"cost" options:0 context:kLineItemContext];
    [lineItems insertObject:newItem atIndex:index];
}

- (void)removeObjectFromLineItemsAtIndex:(unsigned)index
{
    [[lineItems objectAtIndex:index] removeObserver:self forKeyPath:@"cost"];
    [lineItems removeObjectAtIndex:index];
}

- (void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context
{
    if (context == kLineItemContext)
    {
        [self willChangeValueForKey:@"totalCost"];
        [self didChangeValueForKey:@"totalCost"];
    }
}

Autres conseils

Vous pouvez essayer une solution plus courte.

Ajouter au fichier d'en-tête:

@property (retain, readonly) NSDecimalNumber *accountBalance;

Ajouter au fichier d'implémentation

- (NSDecimalNumber *)totalCost
{
    return [self valueForKeyPath:@"InvoiceLineItems.@sum.cost"];
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top