Confused Development

I develop software and I often get confused in the process. I usually find the answers after a while, but a month later I can't remember them. So from now on, I will write them down here.

Tuesday, April 11, 2006

Changing Data Cells in NSTableView

I guess I shouldn't be afraid of posting even the stupidest things here (or most stupid, check this poll).

I recently tried to change the data cell type in an NSTableView (in the column, to be more precise) from the default text field to a check-box, so that I could bind it to a BOOL variable. I didn't see straight away how to do this in Interface Builder, and so started to try doing it programmatically. All kinds of funky problems ensued (read about it here), but the short version is: I couldn't get it to work.

Only when I was informed that you indeed can change the data cell in IB, I figured out how to do it - and guess what, it's amazingly simple, and it works straight away. Just drag any desired cell type (e.g. a check-box) from the "Cocoa Data" palette onto the table column. It's that easy. :-P

Wednesday, April 05, 2006

Dynamically creating a va_list in C ...

... seems to be impossible, from what I can find out on the web.

A va_list is a variable argument list which you can define as an argument to a function (or a method in Objective-C). A prominent example of this is vprintf (see printf and variadic functions on Wikipedia). In Apple's Cocoa library, one example is NSString's initWithFormat:arguments:.

My problem was this: I want to call this method, but I don't know at compile-time which arguments I want to pass. Instead, I create an array with arguments. Now, I thought I would be able to create a va_list from this array and pass it to initWithFormat:arguments:, but, as noted above, this is apparently not possible. So, to make a long story short, I had to conjure up my own mock-up of such a format function. I only need to deal with strings, so basically I scan for occurrences of "%@" (indicates an object in Objective-C) and replace them with the elements from the array. Not very elegant, but it works.

- (NSString *)evaluatePseudoFormat: (NSString *)format
                     withArguments: (NSArray *)array
{
  NSMutableString *evaluatedString = 
    [NSMutableString stringWithString: format];
  NSRange varRange, scanRange;
  int length = [format length];
  scanRange = NSMakeRange(0, length);
  int index = [array count];
  NSString *replacement;
  while ((varRange = [format rangeOfString: @"%@"
      options: NSBackwardsSearch
        range: scanRange]).length > 0 && index >= 0) {
    replacement = [array objectAtIndex: --index];
    [evaluatedString replaceCharactersInRange: varRange 
                                   withString: replacement];
    length = varRange.location;
    scanRange = NSMakeRange(0, length);
  }
  return evaluatedString;
}

Don't ask me why I search backwards. I had some complicated reason for that. After changing some things, the reason became obsolete. However, since the code works, I don't see why I should change it now. ;-)