2009-03-04 24 views
9

したがって、InvoiceとInvoiceLineItemの2つのオブジェクトがあります。 InvoiceLineItemにはcostというプロパティがあり、他のプロパティに基づいて動的に作成されます。私が使用するKVO /バインディングを手助けするために:計算された値に基づいて計算された値にKVOを設定する

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

これは素晴らしいです。 serivceCostのようなプロパティを編集すると、テーブルビューのメインコストが正常に更新されます。

Invoiceオブジェクトには、InvoiceLineItemsのNSMutableArrayがあります。請求書にはtotalCostという同様のプロパティがあります。これは広告申込情報を繰り返し処理して計算され、広告申込情報が削除済みとしてマークされていない限り(理由を同期するために使用します)、費用が加算されてtotalCostが作成されます。

私の質問/問題。請求書のtotalCostを設定して、広告申込情報の費用のいずれかが変更されたときにKVO /バインディングと連携するようにするにはどうすればよいですか?

私はセットアップを試みた:

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

が、それは動作しません。私はコンソールにエラーで終わる:[<NSCFArray 0x1499ff40> addObserver:forKeyPath:options:context:] is not supported. Key path: cost

答えて

6

私は多くの人間関係が自動KVO伝言のためにサポートされているとは思わない。ドキュメンテーションは、ある意味では明白ではありませんが、一般的に私がKVOを知っていることから、多対多関係のサブキーを観察することは、些細なことではありません。

私はこれを手動で挿入して/削除addObserver/removeObserverコールをやってInvoiceクラスのlineItemsプロパティのために、多くのKVCアクセサを実装することにより、各InvoiceLineItemオブジェクトのcost性質を観察することであろうアプローチような方法メソッドを実行してから、willChangeValueForKey:/ didChangeValueForKey:を使用して手動でtotalCostの変更をトリガーします。したがって、このような何か(約スケッチコード、免責事項など):

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

を追加し、私は自分自身の実装のこの種にかなり近かったが、それは、それは他の誰かから来る聞いて良いことです。しかし、質問すると、will/didChangeの積み重ね...どうしてちょうどdid not changeChange? – zorn

+0

基本的なオブジェクトが正しく実装されていればうまくいくはずです。たとえば、Core Data FAQには次のようなものがあります。 http://developer.apple.com/documentation/Cocoa/Conceptual/CoreData/Articles/cdFAQ.html#//apple_ref/doc/uid/TP40001802-SW3 –

+0

初期のテストではこれが動作します。私はすでに観測の大部分を(実行をサポートするために)適所に持っていました。再度、感謝します。 – zorn

0

あなたが短いソリューションを試してみてください。

ヘッダファイルに追加します。

@property (retain, readonly) NSDecimalNumber *accountBalance; 

は、実装ファイルに

- (NSDecimalNumber *)totalCost 
{ 
    return [self valueForKeyPath:@"[email protected]"]; 
}