I have a fairly lengthy if statement. The if statement examines a string "type" to determine what type of object should be instantiated. Here's a sample...
if ( [type rangeOfString:@"coin-large"].location != NSNotFound )
{
... create large coin ...
mgr = gameLayer.coinLargeMgr;
}
else if ( [type rangeOfString:@"coin-small"].location != NSNotFound )
{
mgr = gameLayer.coinLargeMgr;
}
... more else statements ...
myObject = [mgr getNewObject];
The "else-if" statements continue for other object types which stand at about 20 right now and that number is likely to increase. This works quite well but in terms of maintenance and efficiency I think it could be improved. My leading candidate right now is to create an NSDictionary
keyed on the object type string (coin-small, coin-large, etc.) and with the value of the manager object that should be tied to that type. The idea being that this would be a quick look for the type of object I need to create. Not sure this is the best approach, continuing to look at other options but am curious what folks here might have done for a similar problem. Any help/feedback is greatly appreciated.
You can use an NSDictionary filled with ObjC 'Blocks' to do a switch-like statement which executes the desired code. So make a dictionary with your string keys mapped to a block of code to execute when each is found:
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
^{ NSLog(@"found key1"); }, @"key1",
^{ NSLog(@"found key2"); }, @"key2",
nil];
You'll probably prepare this dictionary only once at some early stage like in a constructor or a static initializer so that it is ready when your later code executes.
Then instead of your if/else block, slice out the string key from whatever intput you are receiving (or maybe you won't need to slice it, whatever):
NSString *input = ...
NSRange range = ...
NSString *key = [input substringWithRange:range];
And do the (fast) dictionary lookup for the code to execute. Then execute:
void (^myBlock)(void) = [dict objectForKey:key];
myBlock();
The dictionary approach would be easily doable. Assuming the various managers have been boiled down to specific instances when you create the dictionary, it'd be just the same as almost any object-oriented language:
NSDictionary *stringsToManagers =
[NSDictionary dictionaryWithObjectsAndKeys:
@"coin-large", gameLayer.coinLargeMgr,
@"coin-small", gameLayer.coinSmallMgr,
nil];
// this is assuming that type may contain multiple types; otherwise
// just use [stringsToManagers objectForKey:string]
for(NSString *string in [stringsToManagers allKeys])
{
if([type rangeOfString:string].location != NSNotFound)
{
[[stringsToManagers objectForKey:string] addNewObject];
// or get it and store it wherever it should go
}
}
If all the managers do is vend appropriate objects, the more object-oriented approach might be:
NSDictionary *stringsToClasses =
[NSDictionary dictionaryWithObjectsAndKeys:
@"coin-large", [LargeCoin class],
@"coin-small", [SmallCoin class],
nil];
// this is assuming that type may contain multiple types; otherwise
// just use [stringsToManagers objectForKey:string]
for(NSString *string in [stringsToManagers allKeys])
{
if([type rangeOfString:string].location != NSNotFound)
{
id class = [stringsToManagers objectForKey:string];
id newObject = [[class alloc] init];
// this is exactly the same as if, for example, you'd
// called [[LargeCoin alloc] init] after detecting coin-large
// within the input string; you should obviously do something
// with newObject now
}
}
That could save you having to write any managers if your program structure otherwise fits.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With