0
votes

New to SO; my first question:

Re: Core Data, document based app using bindings:

I have an NSTableView bound to an NSArrayController, bound to an entity, LineItem, with several columns bound to the following LineItem attributes/properties: amount, price, and total. I'm using +keyPathsForValuesAffectingTotal to observe changes in amount and price. The property, total, updates instantly with any changes. I have another entity, Item. It has a one to many relationship (items) with LineItem since every Item can have many LineItems. Item also has an NSTableView bound to an NSArrayController, which is bound to its respective entity, Item. This table has several columns as well, but one is, lineItemTotal ([email protected]).

- (NSNumber *)lineItemTotal {
     float totalOfAllLineItemTotals = [[self valueForKeyPath:@"[email protected]"]floatValue];
     [self willAccessValueForKey:@"lineItemTotal"];
     return [NSNumber numberWithFloat:totalOfAllLineItemTotals];
     [self didAccessValueForKey:@"lineItemTotal"];
     return [NSNumber numberWithFloat:totalOfAllLineItemTotals];
}

The lineItemTotal value updates instantly with the use of an NSNotification NSManagedObjectContextObjectsDidChangeNotification, which calls my selector, updateLineItemTotal: which sends a message: [self.view setNeedsDisplay:YES]; Everything works fine... However, this view should look like a receipt. As such, I have an NSTextField underneath the LineItem Table to show the total, as the user would expect. I have tried binding it to the same NSArrayController that Item is, but this does not work. In the bindings Inspector, I cannot choose arrangedObjects for the Controller Key, since it isn't a table. (this is how the Item Table is set up and working fine) My only choice is 'selection' for the Controller Key. In any case, it always shows the correct value, but only after I create a new Item instance (via NSButton bound to add:) and return to the old Item instance. It does not update instantly like everything else: a user would find this unprofessional. I've tried the suggestions of Hillegass, searched Stack Overflow, and Apple's recommended work arounds regarding updating values when dealing with an NSSet. Apple recommends setting up a notification. I did that and this time it didn't work. I've tried all the obvious workarounds with no success. I believe it comes down to KVC & KVO; unfortunately, Apple has little support for these powerful tools when working with NSSets, at least not on the surface. Any help would be appreciated.

1

1 Answers

0
votes

The first problem I see here is that you appear to be returning from this method before all the statements have executed:

- (NSNumber *)lineItemTotal {
     float totalOfAllLineItemTotals = [[self valueForKeyPath:@"[email protected]"]floatValue];
     [self willAccessValueForKey:@"lineItemTotal"];
     return [NSNumber numberWithFloat:totalOfAllLineItemTotals];
     // Anything below here will never be executed.
     [self didAccessValueForKey:@"lineItemTotal"];
     return [NSNumber numberWithFloat:totalOfAllLineItemTotals];
}

Even so, I took a few minutes and coded this up, and it appears from my experience that the collection operators (i.e. @sum) don't work with CoreData lazy fetched sets. Any attempts I made netted me errors like:

[<_NSFaultingMutableSet 0x101922270> addObserver:forKeyPath:options:context:] is not supported. Key path: @sum.total

Luckily, it appears that you can use the NSArrayController to enable this collection operator. I put the version I coded up on github. I believe I have covered all the bases you were trying to achieve there. I've got the master/detail table views and the extra text field, all live updating, etc.