PDA

View Full Version : Newb question: Calculating values across a row in a NSTableView




elorc
Apr 10, 2009, 02:54 PM
I have an NSTableView with four columns in a document-based Cocoa app. This tableview uses an NSMutableArray to hold its values. The four columns are:

1: User's name
2: Starting Balance
3: Deductions
4: Current Balance

What I want to happen is every time columns 2 or 3 are changed, I want the program to recalculate the value displayed in column 4.

I'm not really sure how this is done since I'm still a big newb with Objective C. :D Could someone provide some information or some sample code? Thanks!


* Update: Okay, I figured out how to make that last column editable so I removed that section of the question. I didn't realize it was as easy as selecting the column and unchecking the "Editable" box. :)



kainjow
Apr 10, 2009, 06:13 PM
Are you using bindings, or a datasource? If bindings, you'll need to observe the array for changes to those fields. If using a datasource, you need to implement tableView:setObjectValue:forTableColumn:row:. With either one you need to get the selected object and calculate and update Current Balance based on the other values, then reload the table.

elorc
Apr 14, 2009, 08:45 PM
Sorry it's been a while. :) ok so I'm making some progress here but I hit an issue I'm not quite sure I understand.

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqual:@"finalBalance"])
{
NSLog(@"No need to update for finalBalance.");
return;
}

NSUndoManager *undo = [self undoManager];
id oldValue = [change objectForKey:NSKeyValueChangeOldKey];

if (oldValue == [NSNull null])
{
oldValue = nil;
}

if ([keyPath isEqual:@"usersName"])
{
NSLog(@"Don't update for usersName change");
}
else
{
// Update finalBalance
int iStartValue = [object startingBalance];
NSLog(@"The value of iStartValue is %d", iStartValue);

int iAdjustment = [object deductionsFromBal];
NSLog(@"The value of iAdjustment is %d", iAdjustment);

int iNewValue = iStartValue - iAdjustment;
NSLog(@"The value of iNewValue is %d", iNewValue);

[object setValue:iNewValue forKeyPath:@"finalBalance"];
NSLog(@"The finalBalance for %@ has been adjusted to %d", object, iNewValue);
}

[[undo prepareWithInvocationTarget:self] changeKeyPath:keyPath
ofObject:object
toValue:oldValue];

[undo setActionName:@"Edit"];
}

At the line where I have [object setValue:iNewValue forKeyPath:@"finalBalance"];, I get this in the code:

warning: passing argument 1 of 'setValue:forKeyPath' makes pointer from integer without a cast

When I edit one of these columns in the program, it crashes to gdb. What am I doing wrong here?

eddietr
Apr 14, 2009, 09:12 PM
At the line where I have [object setValue:iNewValue forKeyPath:@"finalBalance"];, I get this in the code:

warning: passing argument 1 of 'setValue:forKeyPath' makes pointer from integer without a cast

When I edit one of these columns in the program, it crashes to gdb. What am I doing wrong here?

[NSObject setValue:forKeyPath] expects a pointer to an object. It can't take a scalar directly. So you have to wrap your int in an NSNumber like so:


[object setValue: [NSNumber numberWithInt:iNewValue] forKeyPath:@"finalBalance"];


Or if that object happens to have a setter for finalBalance that takes an int, you can just use that directly.


[object setFinalBalance:iNewValue];


Or if finalBalance is a property:


object.finalBalance = iNewValue;

elorc
Apr 14, 2009, 09:18 PM
Ugh, I'm an idiot. lol. I forgot all about that, eddietr. That works exactly as I intended it to. Thank you!