NSTableView cross-coupling rows when editing strings?
NSTableView cross-coupling rows when editing strings?
- Subject: NSTableView cross-coupling rows when editing strings?
- From: Graham Cox <email@hidden>
- Date: Fri, 19 Dec 2008 10:28:42 +1100
I have a weird problem with NSTableView that I'm having trouble
getting to the bottom of. The situation is a little complicated...
I have an array of objects. The table shows the properties of these
objects, one object per row, one property per column, as usual. One of
the properties of the object is its 'representedObject', which is a
further object that can be one of five specific classes. To store
these, the custom object has a mutable dictionary, which uses a string
key, one for each class (the key is derived from the Class, but I'm
pretty sure that's not important here). The overall container of these
custom objects has a setting indicating which of the five classes its
objects should be delivering.
To edit the custom objects, the table view has a column for the
representedObject property. According to the current setting, I swap
in a different type of dataCell for the table column appropriate to
the class to be edited.
The five kinds of representedObject are a) a custom class of my own,
b) a NSColor, c) a NSString, d) a NSValue and d) an NSImage.
Corresponding to these I set the dataCell to a,d) NSImageCell, b) a
custom cell type to handle colours, c,d) a NSTextFieldCell.
The custom colour cell and the image cell situation works fine. But
when I'm using the NSTextFieldCell, I get interference between rows. I
can set the text for row 0 for example, but then when I start editing
row 1 (or any other row), the existing string is first set to empty,
then to whatever I enter - all rows that have a string set end up with
the same string. Tracing in the debugger I can see they are all
retaining the same NSString object. It's as if the NSTextFieldCell
isn't editing a copy of the string.
I've been staring at this for so long now I just can't see the wood
for the trees. Any ideas? Note that I'm not using bindings or any
hidden magic other than KVC - just a classic dataSource. Relevant bits
of code (I think) follow.
Data source - nothing up my sleeve here folks:
- (NSInteger) numberOfRowsInTableView:(NSTableView*) aTableView
{
#pragma unused(aTableView)
return [mTransformer countOfBins];
}
- (id) tableView:(NSTableView *)aTableView objectValueForTableColumn:
(NSTableColumn*) aTableColumn row:(NSInteger) rowIndex
{
#pragma unused(aTableView)
return [[[mTransformer bins] objectAtIndex:rowIndex] valueForKey:
[aTableColumn identifier]];
}
- (void) tableView:(NSTableView*)aTableView setObjectValue:anObject
forTableColumn:(NSTableColumn*) aTableColumn row:(NSInteger) rowIndex
{
#pragma unused(aTableView)
NSString* ident = [aTableColumn identifier];
if([ident isEqualToString:@"index"])
return;
DKOBin* bin = [[mTransformer bins] objectAtIndex:rowIndex];
[bin setValue:anObject forKey:ident];
}
Here's where I switch the table column's cell according to the data
type of the representedObject:
- (void) setOutputType:(int) aType
{
[mTransformer setBinDataType:aType];
// set title of column header
NSString* title = [self titleForDataType:aType];
NSTableColumn* tc = [mBinsTable
tableColumnWithIdentifier:@"representedObject"];
NSTableHeaderCell* thecell = [tc headerCell];
[thecell setTitle:title];
// the cell type must be set to be appropriate to the class of data
expected from -representedObject
// for styles/images this is an image, colours = special colour
cell, text and number = text cell.
NSCell* aCell = [self dataCellForType:aType];
[aCell setEditable:YES];
[aCell setEnabled:YES];
[tc setDataCell:aCell];
[mBinsTable reloadData];
[mDataTypePopUpButton selectItemWithTag:aType];
[mBlendColoursButton setEnabled:aType == kBinOutputTypeColour];
}
The -dataCellForType: method just alloc/init/autoreleases a cell of
the relevant class.
Here's where the actual object's representedObject property is
actually set:
- (void) setRepresentedObject:(id) anObject
{
// each bin is able to store a variety of represented objects of
unique class. The class is used as a key.
// The set data type of the container is used to pick the appropriate
class when -representedObject is invoked.
if( anObject )
{
// what class are we expecting? Sanity check the object against this:
Class expectedClass = [DKOBinningDataTransformer classForDataType:
[[self container] binDataType]];
if([anObject isKindOfClass:expectedClass])
{
NSString* key = NSStringFromClass(expectedClass);
NSLog(@"bin %@ setting object (%p) '%@' for key '%@'", self,
anObject, anObject, key );
[mRepresentedObjects setObject:anObject forKey:key];
}
}
}
- (id) representedObject
{
NSString* key = NSStringFromClass([DKOBinningDataTransformer
classForDataType:[[self container] binDataType]]);
id obj = [mRepresentedObjects objectForKey:key];
NSLog(@"retrieving object from bin %@, key = '%@', obj = (%p) '%@'",
self, key, obj, obj );
return obj;
}
thanks for any insight/help...
--Graham
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden