views:

54

answers:

1

I like the idea of abstracting CellControllers in a heterogeneous UITableView as suggested by Matt Gallagher. However in the case of typical push-detail-view behavior, I find myself creating nearly-identical variants of LinkRowCellController that differ only by the detail view controllers' init methods -- init:, initWithBook:, initWithMagazine:, initWithHelpURLString:andTopic:, etc.

It seems like I could change the designated initializer to take a dictionary of property keys and initial arguments and have the LinkRowCellController initWithProperties: method set up the properties using setValueForKey: on the pairs passed in.

That solution seems to give up compile-time checking of the init arguments. What is the best practice in Objective-C for heterogeneous inits in otherwise homogeneous code?

UPDATE:

Based on jlehr's answer below I implemented a superclass with a single method initWithDictionary:(NSDictionary *)dict that everything inherits from:

- (id)initWithDictionary:(NSDictionary *)dict
{
 if ((self = [super init]) != nil)
 {
  for (id key in dict) {
   [self setValue:[dict objectForKey:key] forKey:key];
  }
 }
 return self;
}
+2  A: 

It's not uncommon to have an -initWithDictionary: method in situations like these. However, all you'd need for the property values would be -initWithObject: -- there'd be no need to translate the Book or Magazine to a dictionary, because you can send -valueForKey: directly to the model objects themselves, as needed. (See NSKeyValueCoding for more details).

But I'd be tempted to initialize the CellController with a dictionary containing configuration info, such as headings and footers for the group, as well as settings for individual cells, such as accessory, image file path, key paths for the model values, etc. That would open the door to using a plist file for the config info for your CellControllers (which I'd be tempted to call CellGroups cause they're really just groups of cells -- but that's just me).

And then, yes, you'd be trading compile-time checking for flexibility and a reduction in code size. But then again this is a fail-fast scenario (i.e., you'll get runtime errors right away when you goof up a key path), so I think it's a pretty decent trade-off. In exchange, whenever you need to add a new table view, all you'd need to do is create a new plist. And you could initialize your CellGroups with something like this:

- (id)initWithObject:(id)anObject configurationInfo:(NSDictionary *)info;

(And, yes, you could just stick the object inside the dictionary, but I don't see that as a win, especially if the dictionary is being fetched by reading a plist from the file system.)

jlehr
It looks clean. I've moved on to a different sticky problem set but let me try this out when I come back.
iPhoneDollaraire
I tried it and it works like a champ! (So much so that I'm surprised it's not a standard method of NSObject?)I'm using this for detail controllers whose values are set at run-time so I'm not sure the plist approach will help me this time.
iPhoneDollaraire