Question

As a complete Coca beginner I need help to do a calculation on a core data entity. Let's assume the entity has 3 attributes, a, b, and c.

Where c = a * b

When I change the entry for a in the table view with the columns a, b and c I want c to be recalculated.

So far I have sub-classed an array controller myArrayController from NSArrayController and set it as the custom class in the identity inspector.

In QT I could have worked with a signal emitted by the table view in case a cell is changed. How would I do it in Cocoa? If I control-drag a button and create an action, it is obviously triggered when the button is clicked. But with a Text Field Cell...? How do I calculate c when the value in column a has been changed? (my first idea would be to ctrl-drag an action into the array controller; but to be honest I have not understood the mechanics well enough and could not find a suitable example in books to judge if I am heading in the wrong direction)

Was it helpful?

Solution 2

Based on Jack Nutting and Peter Clark's "Learn Cocoa on the Mac" chapter 8, page 186 I found the following solution:

I removed attribute c from the cocoa model and created a managedObject subclass. In this suclass I had to implement 2 additional methods:

- (double) c
{
    double c = [[self valueForKey:@"a"] doubleValue] *[[self valueForKey:@"b"] doubleValue]] ;

    return c;
}

+ (NSSet *)keyPathsForValuesAffectingC {

    return [NSSet setWithObjects:@"a", @"b", nil];
}

Then bind the "text field cell - table view cell" to "Table Cell View" (and not the array controller, as described in the book).

And you should be good to go. :-)

I tried it out and could verify that it worked. But thanks to Oleg I got on the right track and I am sure his solution also has its benefits. Thanks again!

OTHER TIPS

At first:

override accessor method in entity class

@implementation Entity

@dynamic a;
@dynamic b;
@dynamic c;

-(NSNumber*) c
{
    return [NSNumber numberWithDouble:[self.a floatValue]*[self.b integerValue]];
}

-(void)didChangeValueForKey:(NSString *)key
{
    [[NSNotificationCenter defaultCenter] postNotificationName:@"needSave" object:self];
    [[NSNotificationCenter defaultCenter] postNotificationName:@"needUpdate" object:self];
    [super didChangeValueForKey:key];
}

@end

In your controller you should add this in didLoad method or applicationDidFinishLaunching if it is a appDelegate:

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(updateTables)
                                             name:@"needUpdate"
                                           object:nil];

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(save)
                                             name:@"needSave"
                                           object:nil];

-(void)updateTables
{
    [table reloadData];
}

-(void)save
{
    NSError *err = nil;
    [self.managedObjectContext save:&err];
}

So, when array controller will access to c property, she will recalculated. But don't forget set Transient property for c property in attribute inspector of xcdatamodel.

enter image description here

And you should never use setC: method.

Second:

You don't should write subclass of NSArrayController for working with custom entities.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top