Pregunta

Entonces tengo dos objetos, Factura y InvoiceLineItem.InvoiceLineItem tiene una propiedad llamada cost y se crea dinámicamente en función de otras propiedades.Para ayudar con los KVO/enlaces utilizo:

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

Esto funciona muy bien.Cuando edito una propiedad como serivceCost, el costo principal en la Vista de tabla se actualiza bien.

En el objeto Factura tengo un NSMutableArray de InvoiceLineItems.La factura tiene una propiedad similar llamada totalCost.Se calcula iterando sobre las líneas de pedido y, siempre que la línea de pedido no esté marcada como eliminada (lo que hago por motivos de sincronización), suma los costos y crea el costo total.

Ahora mi pregunta/problema.¿Cómo configuro el costo total de la factura para que funcione con KVO/vinculaciones cuando uno de los costos de la línea de pedido ha cambiado?

Intenté configurar:

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

pero no funciona.Termino con un error en la consola: [<NSCFArray 0x1499ff40> addObserver:forKeyPath:options:context:] is not supported. Key path: cost

¿Fue útil?

Solución

No creo que se admitan muchas relaciones para la propagación automática de KVO. La documentación no dice explícitamente de una forma u otra, pero por lo que sé de KVO en general, observar subclaves de una relación de muchos tiende a ser no trivial.

La forma en que abordaría esto sería observar manualmente la propiedad cost de cada objeto InvoiceLineItem, implementando los accesos KVC a la propiedad lineItems en la clase Factura haciendo una llamada addObserver / removeObserver en inserte / elimine métodos, respectivamente, y luego active el cambio totalCost manualmente usando willChangeValueForKey: / didChangeValueForKey :. Entonces, algo como esto (código esbozado, descargos de responsabilidad, 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"];
    }
}

Otros consejos

Puede intentar una solución más corta.

Añadir al archivo de encabezado:

@property (retain, readonly) NSDecimalNumber *accountBalance;

Añadir al archivo de implementación

- (NSDecimalNumber *)totalCost
{
    return [self valueForKeyPath:@"InvoiceLineItems.@sum.cost"];
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top