2009-03-04 41 views
9

Vì vậy, tôi có hai đối tượng, Invoice và InvoiceLineItem. InvoiceLineItem có thuộc tính được gọi là cost và được tạo động dựa trên các thuộc tính khác. Để trợ giúp với KVO/các ràng buộc tôi sử dụng:Thiết lập KVO cho các giá trị được tính toán, dựa trên các giá trị được tính toán

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

Điều này thật tuyệt vời. Khi tôi chỉnh sửa một thuộc tính như serivceCost chi phí chính trong các cập nhật Bảng Xem tốt.

Trong đối tượng Hoá đơn, tôi có NSMutableArray của InvoiceLineItems. Hóa đơn có thuộc tính tương tự được gọi là totalCost. Nó được tính bằng cách lặp qua các chi tiết đơn hàng và miễn là chi tiết đơn hàng không được đánh dấu là đã xoá (mà tôi làm vì lý do đồng bộ hóa), nó sẽ tăng thêm chi phí và tạo tổng cộng.

Hiện câu hỏi/vấn đề của tôi. Làm cách nào để tôi thiết lập totalCost của Hoá đơn để nó hoạt động với KVO/các ràng buộc khi một trong các chi phí của chi tiết đơn hàng đã thay đổi?

tôi đã cố gắng thiết lập:

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

nhưng nó không hoạt động. Tôi gặp lỗi trong bảng điều khiển: [<NSCFArray 0x1499ff40> addObserver:forKeyPath:options:context:] is not supported. Key path: cost

Trả lời

6

Tôi không tin rằng nhiều mối quan hệ được hỗ trợ cho tự động hóa KVO. Các tài liệu không nói explicity cách này hay cách khác, nhưng từ những gì tôi biết của KVO nói chung, quan sát subkeys của một mối quan hệ nhiều có xu hướng không tầm thường. Cách tôi sẽ tiếp cận này sẽ là để quan sát thủ công thuộc tính cost của mỗi đối tượng InvoiceLineItem, bằng cách thực hiện nhiều KVC accessors cho thuộc tính lineItems trên lớp Invoice thực hiện lệnh gọi addObserver/removeObserver trong việc chèn/xóa phương pháp, tương ứng, và sau đó kích hoạt các thay đổi totalCost bằng tay sử dụng willChangeValueForKey:/didChangeValueForKey :. Vì vậy, một cái gì đó như thế này (khoảng phác thảo mã, từ chối trách nhiệm vv):

- (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

Tôi đã khá gần với loại triển khai bản thân mình nhưng rất tốt để nghe nó đến từ một người khác. Câu hỏi mặc dù, xếp chồng của will/didChange ... tại sao không chỉ gọi didChange? – zorn

+0

Tôi nghĩ rằng nó sẽ làm việc, nếu các đối tượng tiềm ẩn thực hiện nó một cách chính xác. Ví dụ: Câu hỏi thường gặp về dữ liệu cốt lõi cho thấy một cái gì đó giống như thế này: http://developer.apple.com/documentation/Cocoa/Conceptual/CoreData/Articles/cdFAQ.html#//apple_ref/doc/uid/TP40001802-SW3 –

+0

Với một số thử nghiệm ban đầu, công trình này. Tôi đã có hầu hết các công cụ quan sát tại chỗ (để hoàn tác hỗ trợ). Cảm ơn một lần nữa. – zorn

0

Bạn có thể thử một giải pháp ngắn hơn.

Thêm vào các tập tin tiêu đề:

@property (retain, readonly) NSDecimalNumber *accountBalance; 

Thêm vào tập tin thực hiện

- (NSDecimalNumber *)totalCost 
{ 
    return [self valueForKeyPath:@"[email protected]"]; 
} 
Các vấn đề liên quan