用Objective-C中的替代构造替换大量if语句的方法

Rob*_*gal 5 objective-c

我有一个相当冗长的if声明.if语句检查字符串"type"以确定应该实例化的对象类型.这是一个样本......

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];
Run Code Online (Sandbox Code Playgroud)

"else-if"语句继续用于其他目前约为20的对象类型,并且该数字可能会增加.这很有效,但在维护和效率方面,我认为可以改进.我现在的主要候选人是创建一个NSDictionary键入对象类型字符串(coin-small,coin-large等)以及应该绑定到该类型的manager对象的值.我的想法是,这将是我需要创建的对象类型的快速查找.不确定这是最好的方法,继续看其他选项,但很好奇这里的人们可能为类似的问题做了什么.非常感谢任何帮助/反馈.

Tod*_*orf 6

您可以使用填充了ObjC'Blocks'的NSDictionary来执行类似开关的语句,该语句执行所需的代码.因此,创建一个字典,将字符串键映射到一个代码块,以便在找到每个代码时执行:

NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
                      ^{ NSLog(@"found key1"); }, @"key1", 
                      ^{ NSLog(@"found key2"); }, @"key2", 
                      nil];
Run Code Online (Sandbox Code Playgroud)

您可能只在早期阶段(如构造函数或静态初始化程序)准备此字典一次,以便在以后的代码执行时准备就绪.

然后,而不是你的if/else块,从你收到的任何输入切出字符串键(或者你可能不需要切片,无论如何):

NSString *input = ...
NSRange range = ...
NSString *key = [input substringWithRange:range]; 
Run Code Online (Sandbox Code Playgroud)

并执行(快速)字典查找以执行代码.然后执行:

void (^myBlock)(void) = [dict objectForKey:key];
myBlock();
Run Code Online (Sandbox Code Playgroud)

  • 实际上,无论您是否使用ARC,都需要复制Block.ARC仅自动处理返回案例; 作为一个论点,它仍然必须被复制. (2认同)

Tom*_*mmy 5

字典方法很容易实现.假设在创建字典时各种管理器已经归结为特定的实例,它几乎与任何面向对象的语言相同:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

如果所有管理者都做了适当的对象,那么面向对象的方法可能更多:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

如果你的程序结构不合适,这可以节省你必须编写任何经理.