More Choices

I want to follow up on Monday’s post about my ChoiceMenu class; that class contained one particular line of code that made it a lot more useful and flexible. Perhaps I’m inordinately proud of it, but I think it’s worth a mention, and I didn’t have time to discuss it before.

The Line

This is the line of code in which I’m interested, taken from the tableView:cellForRowAtIndexPath: method:

cell.text = [NSString stringWithFormat:@"%@",[choices objectAtIndex:indexPath.row]];

The significance of this line is that it allows the choices passed to a ChoiceMenu to be an array of arbitrary objects, as opposed to the NSStrings a simpler implementation would have required.

SELECT and OPTIONs

This design choice was motivated by a desire to emulate some of the flexibility of HTML’s SELECT/OPTION tags; within a SELECT, each choice has three distinct attributes:

  • An index (or position) in the overall list of choices
  • An internal value
  • A displayed value

If I had required that the choices passed to a ChoiceMenu consist only of the strings displayed to the user, each choice would have had only two of these three attributes.

Example

Of course, it’s perfectly legitimate to use a simple array of strings as the choices for a ChoiceMenu; this sort of code is just fine:

NSArray* choices = [[NSArray alloc] initWithObjects:@"foo",@"bar",@"baz",nil];
ChoiceMenu* cm	= [[ChoiceMenu alloc] initWithChoices:choices];
[choices release];

If you want to do something more elaborate, however, you can define a little helper class like this:

@interface Choice : NSObject {
	NSString*	label;
	NSObject*	value;
}

@property (nonatomic, retain) NSString* label;
@property (nonatomic, retain) NSObject* value;

- (id)initWithLabel:(NSString*)a_label value:(NSObject*)a_value;

+ (id)choiceWithLabel:(NSString*)a_label value:(NSObject*)a_value;

@end
@implementation Choice

@synthesize label;
@synthesize value;


// New D. I.
- (id)initWithLabel:(NSString*)a_label value:(NSObject*)a_value
{
	if (self = [super init])
	{
		label = [a_label retain];
		value = [a_value retain];
	}
	return self;
}


// Super's D. I.
- (id)init
{
	return (self = [self initWithLabel:nil value:nil]);
}


- (NSString*)description
{
	return label;
}


- (void)dealloc
{
	[label release];
	[value release];
	[super dealloc];
}


+ (id)choiceWithLabel:(NSString*)a_label value:(NSObject*)a_value
{
	return [[[Choice alloc] initWithLabel:a_label value:a_value] autorelease];
}

@end

… and then pass an array of Choices to ChoiceMenu, where each Choice contains an arbitrary object associated with whatever label you think best. When a Choice object is passed back to choiceMenu:didEndWithObject:, you can extract the arbitrary object associated with the user’s selection. (Naturally, you don’t have to use an intermediating class such as Choice if you want to override your classes’ description or descriptionWithLocale: methods, but it seems like that might not always be desirable.)

Perhaps all this isn’t such a big deal, but it appealed to me.

Share and Enjoy:
  • Twitter
  • Facebook
  • Digg
  • Reddit
  • HackerNews
  • del.icio.us
  • Google Bookmarks
  • Slashdot
This entry was posted in iPhone. Bookmark the permalink.

Comments are closed.