【问题标题】:UIAlertController if iOS 8, otherwise UIAlertView如果是 iOS 8,则为 UIAlertController,否则为 UIAlertView
【发布时间】:2014-08-07 20:33:46
【问题描述】:

我想符合 iOS 8 中使用的 UIAlertController,因为 UIAlertView 现在已被弃用。有没有一种方法可以在不破坏对 iOS 7 的支持的情况下使用它?是否可以执行某种 if 条件来检查 iOS 8,否则可以执行其他操作以支持 iOS 7?

【问题讨论】:

  • 仅供参考 - 由于您的部署目标是 iOS 7(或更早版本),您可以使用 UIAlertView。这将使您的代码更简单。
  • 我不知道 Swift 有一个 respondsToSelector ...另外,UIAlertView 在 ios8 中搞砸了,它不会像在 ios 7 中那样滚动,这就是我想要尝试同时使用两者
  • 滚动在 UIAlertController 上也不起作用

标签: ios uialertview ios8 uialertcontroller


【解决方案1】:

请看Erwan的答案(在我的答案下方),因为我认为这是最好的。

--

您可以检查 iOS 版本以使用适当的控件,如下所示:

if (([[[UIDevice currentDevice] systemVersion] compare:@"8.0" options:NSNumericSearch] == NSOrderedAscending)) {
    // use UIAlertView
}
else {
    // use UIAlertController
}

【讨论】:

  • 我在下面发布了我认为更好的方法,检查类是否存在而不是检查操作系统的版本
  • 这是一种执行此检查的脆弱方法。事实上,Apple 建议不要进行此类检查。 Erwan的答案是正确的答案。
  • 永远不要检查代码中的版本号,这是非常糟糕的做法。正如 squarefrog 指出的那样,@Erwan 有更好的解决方案,请始终检查功能/特性。
  • 如前所述,[UIAlertController 类] 的条件评估是首选策略。如果需要检查操作系统的版本,首选约定是比较 NSFoundationVersionNumber -- 详细 here
【解决方案2】:
// Above ios 8.0
float os_version = [[[UIDevice currentDevice] systemVersion] floatValue];
if (os_version >= 8.000000)
{
      //Use UIAlertController    
}
else
{
     //UIAlertView
}

【讨论】:

    【解决方案3】:

    创建简单的utility function 以减少代码

    代码:

    // pass minimum required iOS version
    BOOL isOSSupported(NSString *minRequiredVersion)
    {
        NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
        BOOL isOSSupported = ([currSysVer compare:minRequiredVersion options:NSNumericSearch] != NSOrderedAscending) && 
                                      ![currSysVer isEqualToString:@"Unknown"];
        return isOSSupported;
    }
    


    使用:

    if(isOSSupported("8.0")
    {
    // Code for iOS8 and above
    }
    else
    {
    // Code for iOS7 and below
    }
    



    或者如下使用系统常量NSFoundationVersionNumber_iOS_7_1
    if(floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_7_1)
    {
       // Code for iOS8 and above
    }
    else
    {
       // Code for iOS7 and below
    }
    


    更多选项Link

    【讨论】:

    • 不需要-1 :)),请把你的想法分享给其他人
    • 不好的做法,永远不要检查版本号。始终检查功能/特性。
    • @SHaKie 那么在这种情况下最好使用苹果提供的常量 NSFoundationVersionNumber_iOS_7_1
    • 最好的做法是检查类是否存在,如我上面发布的答案。对于方法,您还可以检查该类是否响应 @selector(yourMethod)
    • @Jageen 恐怕不会。无论您采用哪种方式,检查操作系统版本号都是一种不好的做法。永远不要以这种方式对依赖项进行硬编码,始终检查特性、功能或类的存在。考虑一下; Apple 可能会发布一个类的向后兼容版本,如果他们这样做了,那么您建议的代码将永远不会使用它,因为您的逻辑会查找操作系统版本号而不是该类的存在。
    【解决方案4】:

    我认为检查类是否存在的更好方法(从 iOS 4.2 开始)是:

    if([ClassToBeChecked class]) {
    
       // use it
    
    } else {
    
      // use alternative
    
    }
    

    在你的情况下,那将是:

    if ([UIAlertController class]) {
       // use UIAlertController
    
    } else {
      // use UIAlertView
    
    }
    

    【讨论】:

    • 我试过这样做,但是当我运行 XCode 5 时,我的代码将无法编译。如何验证这确实适用于 iOS7?
    • 这应该被标记为正确答案。始终检查类/特性/常量/函数是否存在,而不是检查 iOS 版本。
    • 如何在 Swift 上实现?
    • 是的,但是如果有人正在编译由某人使用 ios 8 sdk 编写的代码,但他们现在在 xcode 5 上使用 ios 7 sdk,则该代码将无法编译。这就是@huey 遇到的问题,因为他在 xcode 5 上编译, UIAlertController 将无法识别。如果您使用的是最新的 SDK,那么您的答案是正确的,因为当运行 ios7 的手机运行您使用 ios8 构建的应用程序时,它只会在 [UIAlertController 类] 上返回 nil。
    • 对,所以@huey 不应该尝试在 xcode 5 上编译。如果设备使用 ios7,他需要使用 xcode 6 并使用您的代码来防止调用 UIAlertController。我的评论是为了指出它不编译的原因是该类在 ios 7 sdk 上不可用。但是,您的第一个回复说它将适用于 ios7 和 xcode 5,如果该类不可用,则不是这样。
    【解决方案5】:

    正如其他人已经提到的 - 始终检查功能是否存在。我认为最安全的方法如下:

    if (NSClassFromString(@"UIAlertController")) {
        // use UIAlertController
    } else {
        // use UIAlertView
    }
    

    输入带有拼写错误的类名存在明显风险。 :)

    来自 NClassFromString 的文档:

    [返回] 由 aClassName 命名的类对象,如果当前没有加载该名称的类,则返回 nil。如果 aClassName 为 nil,则返回 nil。

    可用性 iOS(2.0 及更高版本)

    【讨论】:

    • 这段代码 sn-p 翻译成 Swift 在使用 iOS 7.1 和 8.2 的 iOS 模拟器上可以正常工作,但是如果你在使用 iOS 7.1 的真实设备上测试,你会很遗憾地注意到你永远不会通过代码sn-p的else部分。所以这个 sn-p 的代码是不稳定的,我不建议在生产中使用它。
    • alino-91 的评论是真的。改用 objc_getClass
    【解决方案6】:

    方法一

    通过ios系统版本检查

    #define iOSVersionLessThan(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
    // below ios8 ,create UIAlertView
    if(iOSVersionLessThan(@"7.0")){
         // todo
    
    // ios8 and above ,UIActionController avaliable
    }else{
        // todo
    }
    

    方法二

    通过系统特征检测

    // create UIActionController 
    if([UIActionController class]){
        // todo
    // create UIAlertView
    }else{
        // todo
    }
    

    但是,还有一个名为 PSTAlertController 的第三个库,用于处理向后兼容 iOS 7 的 UIActionSheet 和 UIAlertView。

    参考

    【讨论】:

      【解决方案7】:

      我在 Objective-C 中创建了非常简单的包装器,它同时支持旧的 iOS UIAlertView 和新的 UIAlertViewController

      https://github.com/MartinPerry/UIAlert/

      它还为旧的UIAlertView带来了新的动作块用法

      示例:

      MyAlertMessage * a = [[MyAlertMessage alloc] initWithTitle:@"Hello" WithMessage:@"World"];
      
      [a addButton:BUTTON_OK WithTitle:@"OK" WithAction:^(void *action) { 
        NSLog(@"Button OK at index 0 click"); 
      }];
      
      [a addButton:BUTTON_CANCEL WithTitle:@"Cancel" WithAction:^(void *action) {
        NSLog(@"Button Cancel at index 1 click"); 
      }];
      
      [a show];
      

      【讨论】:

      • 这是否处理多个警报?
      【解决方案8】:

      目标 C(如上所述)

      if ([UIAlertController class]) {
          // use UIAlertController
      
      } else {
          // use UIAlertView
      
      }
      

      斯威夫特

      if objc_getClass("UIAlertController") == nil  {
             // use UIAlertView 
      
      } else {
        // use UIAlertController
      
      }
      

      不要使用if NSClassFromString("UIAlertController") == nil 它不起作用,因为此方法的签名是func NSClassFromString(_ aClassName: String!) -> AnyClass!

      【讨论】:

        【解决方案9】:

        在 Swift 中检查 iOS 版本的解决方案

        switch (UIDevice.currentDevice().systemVersion.compare("8.0.0", options: NSStringCompareOptions.NumericSearch)) {
            case .OrderedAscending:
               println("iOS < 8.0")
        
            case .OrderedSame, .OrderedDescending:
               println("iOS >= 8.0")
        }
        

        此解决方案的缺点:无论您采用哪种方式,检查操作系统版本号都是一种不好的做法。永远不要以这种方式对依赖项进行硬编码,始终检查特性、功能或类的存在。考虑一下; Apple 可能会发布类的向后兼容版本,如果他们这样做了,那么您建议的代码将永远不会使用它,因为您的逻辑会查找操作系统版本号而不是类的存在。

        (Source of this information)

        在 Swift 中检查类是否存在的解决方案

        if (objc_getClass("UIAlertController") == nil) {
           // iOS 7
        } else {
           // iOS 8+
        }
        

        不要使用if (NSClassFromString("UIAlertController") == nil),因为它在使用 iOS 7.1 和 8.2 的 iOS 模拟器上可以正常工作,但是如果你在使用 iOS 7.1 的真实设备上进行测试,你会很遗憾地注意到你永远不会通过 else 部分代码sn-p。

        【讨论】:

        • "不要使用 if (NSClassFromString("UIAlertController") == nil) 因为它在使用 iOS 7.1 和 8.2 的 iOS 模拟器上可以正常工作,但是如果你在使用 iOS 7.1 的真实设备上测试,不幸的是,你会注意到你永远不会通过代码 sn-p 的 else 部分。”那是真实的。我希望我以前读过这篇文章。
        【解决方案10】:

        我编写了一个类来包装 UIAlertView 并使用 UIAlertController。因为程序员是透明的,因此在项目中导入这些类就足够了。此类的实用性在于,在旧项目中有更多 UIAlertView 需要更改。链接:https://github.com/kennymuse/UIAlertView

        【讨论】:

          【解决方案11】:

          试试下面的代码。它适用于 iOS 8 及以下版本。

          if (IS_OS_8_OR_LATER) {
          UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:title message:msg preferredStyle:UIAlertControllerStyleAlert];
          
          UIAlertAction *cancelAction = [UIAlertAction
                                       actionWithTitle:@"OK"
                                       style:UIAlertActionStyleCancel
                                       handler:^(UIAlertAction *action)
                                       {
          
                                       }];
          [alertVC addAction:cancelAction];
          
          [[[[[UIApplication sharedApplication] windows] objectAtIndex:0] rootViewController] presentViewController:alertVC animated:YES completion:^{
          
          }];
          }
          else{
              UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:msg delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil];
              [alert show];
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-11-22
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-04-12
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多