views:

81

answers:

2

I have to initialize a lot of different types of objects based on an integer parameter. They all have the same overall initialization methods.

At the moment I have the following code

#def APPLE 1
#def PEAR 2
switch (t)
{
    case APPLE:
      newobj = [[FApple alloc] init];
      break;
    case PEAR:
      newobj = [[FPear] alloc] init];
      break;
    default:
      retobj = nil;
}

I believe there must be a better way to do this. When I add FOrange I have to go and add another line here.

What would be a better way?

+1  A: 

I don't think there's anything wrong with what you're doing (although using an enumerated type might be less error-prone than #defines), but you might want to check out NSClassFromString(), which does what the name suggests:

- (id)newFruit:(NSString *)classString { //pass in @"FApple" or @"FPear"
    Class fruitClass = NSClassFromString(classString);
    return [[fruitClass alloc] init];
}

This might also have a slight performance hit, though.

eman
+3  A: 

You need a mapping number -> type somewhere, but you don't need to repeat the code:

NSDictionary* d = [NSDictionary dictionaryWithObjectsAndKeys:
                   [FPear  class], [NSNumber numberWithInt:PEAR ],
                   [FApple class], [NSNumber numberWithInt:APPLE],
                   nil];    

Class c = [d objectForKey:[NSNumber numberWithInt:t]];
id x = [[c alloc] init];
Georg Fritzsche
Out of interest, is there a way for [FPear class] to store its own id so that I can just write [NSNumber numberWithInt:[[FPear class] id] ]?
John Smith
@John: Sure, you could use a class method, e.g. `+(NSNumber*)myId`.
Georg Fritzsche