Pergunta

Então, eu tenho dois objetos, Fatura e InvoiceLineItem. InvoiceLineItem tem uma propriedade chamada cost e é dinamicamente criado com base em outras propriedades. Para ajudar com as KVO / ligações que eu uso:

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

Isso funciona muito bem. Quando eu editar uma propriedade como serivceCost o principal custo na exibição de tabela atualizações bem.

No objeto Invoice Eu tenho um NSMutableArray de InvoiceLineItems. Fatura tem uma propriedade similar chamado totalCost. É calculado pela iteração sobre os itens de linha e, enquanto o item de linha não está marcado como excluído (que eu faço para sincronizar razões), acrescenta-se os custos e cria o custoTotal.

Agora, a minha pergunta / problema. Como faço para configurar custoTotal da fatura para que ele funcione com KVO / ligações quando um dos custos do item de linha que mudou?

Eu tentei configurar:

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

mas ele não funciona. Eu acabar com um erro no console: [<NSCFArray 0x1499ff40> addObserver:forKeyPath:options:context:] is not supported. Key path: cost

Foi útil?

Solução

Eu não acredito para-muitos são suportados para propogation KVO automática. A documentação não diz explicitamente uma forma ou de outra, mas pelo que eu sei de KVO em geral, observando subchaves de um para-muitos relação tende a ser não-trivial.

A maneira que eu iria abordar esta seria a observar manualmente a propriedade cost de cada objeto InvoiceLineItem, através da implementação dos acessores KVC para-muitos para a propriedade lineItems na classe Invoice fazendo uma chamada addObserver / removeObserver nos métodos insert / Remover , respectivamente, e, em seguida, provocar a mudança totalCost manualmente usando willChangeValueForKey: / didChangeValueForKey :. Então, algo como isto (código aproximadamente esboçado, renúncias 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"];
    }
}

Outras dicas

Você pode tentar uma solução mais curto.

Adicionar ao arquivo de cabeçalho:

@property (retain, readonly) NSDecimalNumber *accountBalance;

Adicionar a arquivo de implementação

- (NSDecimalNumber *)totalCost
{
    return [self valueForKeyPath:@"InvoiceLineItems.@sum.cost"];
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top