【问题标题】:How to avoid too many if-else statements with NSString in iOS?如何在 iOS 中使用 NSString 避免过多的 if-else 语句?
【发布时间】:2014-09-04 02:30:10
【问题描述】:

大家好,我想使用 iOS8 的新 APNs api 来处理通知操作。在这种方法中:

- (void)application:(UIApplication *)application
handleActionWithIdentifier:(NSString *)identifier
     forRemoteNotification:(NSDictionary *)notification
         completionHandler:(void (^)())completionHandler {

      if ([identifier isEqualToString:@"ACCEPT_IDENTIFIER"]) {
          [self handleAcceptActionWithNotification:notification];
      }
      else if([identifier isEqualToString:@"MAYBE_IDENTIFIER"]) {
          [self handleMaybeActionWithNotification:notification];
      }
      else if ([identifier isEqualToString:@"REJECT_IDENTIFIER"]) {
          [self handleRejectActionWithNotification:notification];
      }
      else if....blah blah blah..
}

在这种情况下,我以后可能不得不用 NSString 编写太多的 if-else 语句,并且我知道一些避免太多 if-else 语句的方法,例如使用 switch,但它不适用于 string 或 NSString案例。

有什么办法可以避免在这个字符串或者 NSString 的情况下写太多的 if-else 语句? 提前致谢。

【问题讨论】:

  • 我认为你的做法是最干净的做法
  • 我同意斯科特的观点。您可能会尝试创建一个数组或字典,其中包含可能的字符串列表和可能的操作列表(要调用的选择器),然后遍历该数组,但这可能是不必要的复杂化。
  • 在其他语言(例如,C#)中,您可以使用switch 语句将字符串作为大小写(不仅仅是ints),但switch 语句只是一系列if/ elses 幕后...
  • 你可以试试这个insobject.blogspot.in

标签: ios objective-c if-statement nsstring


【解决方案1】:

您可以将所有选择器放在字典映射中

NSDictionary* handleMap = @{ 
    @"ACCEPT_IDENTIFIER" : NSStringFromSelector(@selector(handleAcceptActionWithNotification:))
    @"MAYBE_IDENTIFIER" : NSStringFromSelector(@selector(handleMaybeActionWithNotification:))
    @"REJECT_IDENTIFIER" : NSStringFromSelector(@selector(handleRejectActionWithNotification:)])
};

NSString* selString = handleMap[identifier];
if (selString) {
    SEL sel = NSSelectorFromString(selString);
    [self performSelector:sel withObject:notification];
}

handleMap 应该被声明为成员变量,所以它只会被初始化一次。

【讨论】:

    【解决方案2】:

    只要您正确命名处理程序方法,您就可以使用这样的方法 -

    - (void)application:(UIApplication *)application 
    handleActionWithIdentifier:(NSString *)identifier 
    forRemoteNotification:(NSDictionary *)notification 
    completionHandler:(void (^)())completionHandler {
    
        NSString *selectorStr=[NSString stringWithFormat:@"handle%@:", identifier];
    
    
        SEL selector=NSSelectorFromString(selectorStr);
    
        if ([self respondsToSelector:selector]) {
           [self performSelector:selector withObject:notification];
        }
    }
    

    然后您将创建一系列方法,例如

    -(void) handleACCEPT_IDENTIFIER:(NSDictionary *)notification {
      ....
    }
    
    -(void) handleMAYBE_IDENTIFIER:(NSDictionary *)notification {
      ....
    }
    

    等等。

    请注意,此技术将生成编译器警告。为什么请参阅this question 的答案 - 如果您的方法返回void,您可以忽略警告。

    【讨论】:

    • 请注意,如果标识符不是纯粹的内部标识符,这可能会带来巨大的安全风险。如果它是用户生成的,或者由外部应用程序生成的,它可以用于在您的应用程序中执行任意函数。
    • 只要那些任意方法以“handle”开头
    • 是的,这是降低风险的一种方法,但更明确的解决方案(例如 @tia 的解决方案)会更安全。
    • 告诉我如何操纵标识符来执行任意方法
    • 正如你所指出的,它可以用来执行任何以句柄开头的方法。直接使用标识符的惰性实现将允许执行任何选择器。只是说允许外部代理直接指定方法名称通常是一个安全问题。在这种情况下,标识符理论上仅来自经过身份验证的服务器,因此应该是安全的。对 Web 服务器或命令行处理器使用相同的方法可能非常危险。只需要知道你的用途是什么以及字符串来自哪里。
    【解决方案3】:

    它可能看起来很多,但我认为这是一种很好的代码结构。
    易于阅读,易于维护。
    因为它是显式的,所以关键字搜索和代码浏览总是微不足道的。 调用者图生成和静态分析也将更彻底地完成(有限制)。

    一些不喜欢这种模式的程序员说“太多了”。
    我不明白这个“太多”点的根据是什么。
    对谁来说太多了?打字员?键盘硬件?

    我总是更喜欢简单明了的代码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多