Domanda

Quindi ho due oggetti, Invoice e InvoiceLineItem. InvoiceLineItem ha una proprietà chiamata cost e viene creata dinamicamente in base ad altre proprietà. Per aiutare con il KVO / bind che uso:

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

Funziona benissimo. Quando modifico una proprietà come serivceCost, il costo principale nella vista tabella si aggiorna bene.

Nell'oggetto Invoice ho un NSMutableArray di InvoiceLineItems. La fattura ha una proprietà simile chiamata totalCost. Viene calcolato ripetendo gli elementi pubblicitari e purché l'elemento pubblicitario non sia contrassegnato come eliminato (cosa che faccio per motivi di sincronizzazione) aumenta i costi e crea totalCost.

Ora la mia domanda / problema. Come faccio a impostare TotalCost di Invoice in modo che funzioni con KVO / associazioni quando uno dei costi dell'elemento pubblicitario è cambiato?

Ho provato a configurare:

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

ma non funziona. Finisco con un errore nella console: [<NSCFArray 0x1499ff40> addObserver:forKeyPath:options:context:] is not supported. Key path: cost

È stato utile?

Soluzione

Non credo che molte relazioni siano supportate per la propagazione automatica KVO. La documentazione non dice esplicitamente in un modo o nell'altro, ma da quello che so di KVO in generale, osservare le sottochiavi di una relazione a molti tende ad essere non banale.

Il modo in cui mi avvicinerei a questo sarebbe quello di osservare manualmente la proprietà cost di ogni oggetto InvoiceLineItem, implementando i molti accessori KVC per la proprietà lineItems sulla classe Invoice facendo una chiamata addObserver / removeObserver nella inserire / rimuovere i metodi, rispettivamente, e quindi attivare manualmente la totalCost modifica usando willChangeValueForKey: / didChangeValueForKey :. Quindi qualcosa del genere (codice approssimativamente abbozzato, dichiarazioni di non responsabilità ecc.):

- (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"];
    }
}

Altri suggerimenti

Potresti provare una soluzione più breve.

Aggiungi al file di intestazione:

@property (retain, readonly) NSDecimalNumber *accountBalance;

Aggiungi al file di implementazione

- (NSDecimalNumber *)totalCost
{
    return [self valueForKeyPath:@"InvoiceLineItems.@sum.cost"];
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top