开发者

subclassing NSCell - [self objectValue] with drawInteriorWithFrame:inView: returns strange results

开发者 https://www.devze.com 2023-02-27 05:27 出处:网络
I have an NSTableView in my main window NIB file that uses a dynamically created datasource - that is, the array of dictionary\'s is created dynamically when required - in one of my classes. So it is

I have an NSTableView in my main window NIB file that uses a dynamically created datasource - that is, the array of dictionary's is created dynamically when required - in one of my classes. So it is not bound by any controllers in IB.

The tableview has 2 columns that have subclassed dataCell's set.

NSTableColumn *detailsColumn = [[tableView tableColumns] objectAtIndex:0];
imageColumnCell *fileDetails = [[[imageColumnCell alloc] init] autorelease];
[detailsColumn setDataCell:fileDetails];
[fileDetails setNumberOfUploads:numberOfFiles];

NSTableColumn *cancelColumn = [[tableView tableColumns] objectAtIndex:1];
cancelButtonCell *cancelCell = [[[cancelButtonCell alloc] init] autorelease];
[cancelColumn setDataCell:cancelCell];

In the <NSTableViewDataSource> file, numberOfRowsInTableView: is set to the correct count of the dynamically created array, and GDB logs it correctly when the table is drawn.

Now the problem comes in. For hypothetic reasons, let's say the array count for the datasource is 1

In both of the subclassed NSCell's I have overwritten the drawInteriorWithFrame:inView: method to handle all the drawing (images, text, buttons etc) inside the table cells. The NSDictionary for each column contains a string (column 1), and an object reference for (column 2).

Based on the example of 1 object in the datasource, if in drawInteriorWithFrame:inView: I were to write the following (in column 2):

NSLog(@"drawInteriorWithFrame: in cancelButtonCell - %@", [self objectValue]);

The expected result (without clicking on the table or scrolling etc) in GDB should be 1 instances of this:

[0000:000] drawInteriorWithFrame: in cancelButtonCell - <object: 0x123456>

And if I were to click or scroll in the table, then it should return the same values for each action within the tableview. However, on first load I get something like this:

[0000:000] drawInteriorWithFrame: in cancelButtonCell - <object: 0x123af06>
[0000:000] drawInteriorWithFrame: in cancelButtonCell - <object: 0x12b3236>

If there are 2 results, then I get 3 log items, and other times 4. In most cases, the method is called 1 more time than it should be.

The second problem, that has only just recently cropped up, is that if you notice the object ID's above, you will see that they are different. If I add 1 item to the datasource, when I call [self objectValue], if the table is redrawn, the object ID's should be the same, as it is a reference - ie. the object is already -alloc'd in the previous class, and I am merely sending the object reference.

I hope this makes sense, but I have been beating my head for the last day trying to see if I am mistakenly duplicating anything anywhere and cannot find any problems. If you need more code let me know. I have tried Google too and have only got reference to this:

http://forum.soft32.com/mac/NSPopUpButtonCell-view-refresh-ftopict46690.html

Thanks in advance.

- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {

  NSString *columnIdentifier = [tableColumn identifier]; 
  NSDictionary *theDict = [fileSourceArray objectAtIndex:row];

  MyAppMethods *appMethods = [MyAppMethods alloc];
  if([appMethods getIsComplete:self])
    return nil;

  if([columnIdentifier isEqualToString:@"fileCancel"]){
    if([[theDict objectForKey:columnIdentifier] isKindOfClass:[ASIFormDataRequest class]]){
      ASIFormDataRequest *fileUploadRequest = [theDict objectForKey:columnIdentifier];
      NSLog(@"in tableView:objectValueForTableColumn:row %@", fileUploadRequest);
      return fileUploadRequest;
    }
  }
  return [theDict objectForKey:columnIdentifier];
}

Additional output for discussion below.

Output from GDB

** 1 file, 1 NSCell set and subclassed ** Here the request stays the same - (i.e. no copying)

[6619:903] <AS开发者_如何学CIFormDataRequest: 0x10ca9b0>
[6619:903] - (id)tableView:objectValueForTableColumn:row: /Users/byronrode/Desktop/Monika and Lubo/DSC_3379.jpg
[6619:903] imageColumnCell.m in - (void)drawInteriorWithFrame:inView: /Users/byronrode/Desktop/Monika and Lubo/DSC_3379.jpg
[6619:903] - (id)tableView:objectValueForTableColumn:row: <ASIFormDataRequest: 0x10ca9b0>
[6619:903] - (id)tableView:objectValueForTableColumn:row: /Users/byronrode/Desktop/Monika and Lubo/DSC_3379.jpg
[6619:903] imageColumnCell.m in - (void)drawInteriorWithFrame:inView: /Users/byronrode/Desktop/Monika and Lubo/DSC_3379.jpg
[6619:903] - (id)tableView:objectValueForTableColumn:row: <ASIFormDataRequest: 0x10ca9b0>

1 file, 2 NSCell's set and subclassed

Here the request changes in the subclass - (i.e. no copying)

[6652:903] <ASIFormDataRequest: 0x103b390>
[6652:903] - (id)tableView:objectValueForTableColumn:row: /Users/byronrode/Desktop/Monika and Lubo/DSC_3379.jpg
[6652:903] imageColumnCell.m in - (void)drawInteriorWithFrame:inView: /Users/byronrode/Desktop/Monika and Lubo/DSC_3379.jpg
[6652:903] - (id)tableView:objectValueForTableColumn:row: <ASIFormDataRequest: 0x103b390>
[6652:903] cancelButtonCell.m in - (void)drawInteriorWithFrame:inView: <ASIFormDataRequest: 0x1221b00>
[6652:903] - (id)tableView:objectValueForTableColumn:row: /Users/byronrode/Desktop/Monika and Lubo/DSC_3379.jpg
[6652:903] imageColumnCell.m in - (void)drawInteriorWithFrame:inView: /Users/byronrode/Desktop/Monika and Lubo/DSC_3379.jpg
[6652:903] - (id)tableView:objectValueForTableColumn:row: <ASIFormDataRequest: 0x103b390>
[6652:903] cancelButtonCell.m in - (void)drawInteriorWithFrame:inView: <ASIFormDataRequest: 0x1227100>


I don't think there's anything to worry about if it's displaying correctly. A table view asks its table columns for "dummy" cells before finalizing their drawing; I suspect that is the cause of the extra -draw... call. Also, the cell copies its object value when setting, so that would obviously give it a new address.

In response to your posting of log messages:

I'm not 100% clear on when exactly these logs are being posted, and what they are displaying, but that looks like what I'd expect to see. In tableView:objectValueForTableColumn:row: you're printing the value that you have in your dictionary, which is the same as the original ASIFormDataRequest. In drawInteriorWithFrame:inView: you're printing the cell's objectValue, which is a copy of that original (i.e., a new object, with a different address in memory).

0

精彩评论

暂无评论...
验证码 换一张
取 消