UIAlertView/UIAlertController iOS 7和iOS 8兼容性

UIAlertView/UIAlertController iOS 7和iOS 8兼容性,ios,swift,uialertview,uialertcontroller,Ios,Swift,Uialertview,Uialertcontroller,我正在使用Swift编写应用程序,我需要显示警报。应用程序必须与iOS 7和iOS 8兼容。由于UIAlertView已被UIAlertController替换,我如何在不检查系统版本的情况下检查UIAlertController是否可用?我一直听说苹果建议我们不要为了确定API的可用性而检查设备的系统版本 这是我在iOS 8上使用的,但在iOS 7上会崩溃,出现“dyld:Symbol not found:\u OBJC\u CLASS\u$\ u UIAlertAction”: 如果我使用i

我正在使用Swift编写应用程序,我需要显示警报。应用程序必须与iOS 7和iOS 8兼容。由于
UIAlertView
已被
UIAlertController
替换,我如何在不检查系统版本的情况下检查
UIAlertController
是否可用?我一直听说苹果建议我们不要为了确定API的可用性而检查设备的系统版本

这是我在iOS 8上使用的,但在iOS 7上会崩溃,出现“
dyld:Symbol not found:\u OBJC\u CLASS\u$\ u UIAlertAction
”:


如果我使用iOS 8的UIAlertView,我会收到以下警告:
警告:尝试在演示或取消过程中从视图控制器取消

如果您想与iOS 7兼容,请不要使用
UIAlertController
。就这么简单


UIAlertView
尚未被替换,它仍能正常工作,并在可预见的未来继续正常工作。

您可以使用以下代码解决问题:-

var device : UIDevice = UIDevice.currentDevice()!;
        var systemVersion = device.systemVersion;
        var iosVerion : Float = systemVersion.bridgeToObjectiveC().floatValue;
        if(iosVerion < 8.0) {
            let alert = UIAlertView()
            alert.title = "Noop"
            alert.message = "Nothing to verify"
            alert.addButtonWithTitle("Click")
            alert.show()
        }else{
            var alert : UIAlertController = UIAlertController(title: "Noop", message: "Nothing to verify", preferredStyle: UIAlertControllerStyle.Alert)
            alert.addAction(UIAlertAction(title: "Click", style:.Default, handler: nil))
            self.presentViewController(alert, animated: true, completion: nil)
        }
var-device:UIDevice=UIDevice.currentDevice()!;
var systemVersion=device.systemVersion;
var iosVerion:Float=systemVersion.bridgeToObjectiveC().floatValue;
如果(IOSVRION<8.0){
let alert=UIAlertView()
alert.title=“Noop”
alert.message=“无需验证”
alert.addButtonWithTitle(“单击”)
alert.show()
}否则{
var-alert:UIAlertController=UIAlertController(标题:“Noop”,消息:“无需验证”,首选样式:UIAlertControllerStyle.alert)
addAction(UIAlertAction(标题:“单击”,样式:。默认,处理程序:nil))
self.presentViewController(警报、动画:true、完成:nil)
}
UIKit必须标记为可选的,而不是必需的


考特西:-

检测模式与Objective-C样式相同

您需要检测当前活动运行时是否能够实例化此类

if objc_getClass("UIAlertController") != nil {

     println("UIAlertController can be instantiated")

      //make and use a UIAlertController

 }
 else {

      println("UIAlertController can NOT be instantiated")

      //make and use a UIAlertView
}
不要试图根据操作系统版本来解决这个问题。你需要检测能力而不是操作系统

编辑

此答案的原始检测器
NSClassFromString(“UIAlertController”)
-O
优化下失败,因此其已更改为当前版本,该版本适用于发布版本

编辑2


NSClassFromString
正在进行Xcode 6.3/Swift 1.2中的所有优化,对于非Swift代码,纯objective-C可以这样做

if ([UIAlertController class])
    {
        // use UIAlertController
        UIAlertController *alert= [UIAlertController
                                      alertControllerWithTitle:@"Enter Folder Name"
                                      message:@"Keep it short and sweet"
                                      preferredStyle:UIAlertControllerStyleAlert];

        UIAlertAction* ok = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault
                                                   handler:^(UIAlertAction * action){
                                                       //Do Some action here
                                                       UITextField *textField = alert.textFields[0];
                                                       NSLog(@"text was %@", textField.text);

                                                   }];
        UIAlertAction* cancel = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleDefault
                                                       handler:^(UIAlertAction * action) {

                                                           NSLog(@"cancel btn");

                                                           [alert dismissViewControllerAnimated:YES completion:nil];

                                                       }];

        [alert addAction:ok];
        [alert addAction:cancel];

        [alert addTextFieldWithConfigurationHandler:^(UITextField *textField) {
            textField.placeholder = @"folder name";
            textField.keyboardType = UIKeyboardTypeDefault;
        }];

        [self presentViewController:alert animated:YES completion:nil];

    }
    else
    {
        // use UIAlertView
        UIAlertView* dialog = [[UIAlertView alloc] initWithTitle:@"Enter Folder Name"
                                                         message:@"Keep it short and sweet"
                                                        delegate:self
                                               cancelButtonTitle:@"Cancel"
                                               otherButtonTitles:@"OK", nil];

        dialog.alertViewStyle = UIAlertViewStylePlainTextInput;
        dialog.tag = 400;
        [dialog show];

    }

您可以使用一个类别来解决这个问题(尽管您需要将其转换为Swift):

但是,如果不想检查系统版本,只需使用

BOOL lowerThaniOS8 = NSClassFromString( @"UIAlertController" ) == nil;

在iOS8的UIView(AlertCompatibility)类别中,有一个新的类
UIAlertController
,它取代了
UIAlertView
UIActionSheet
。从iOS8开始,使用UIAlertController;对于iOS8,在使用UIAlertView和UIActionSheet之前。我认为iOS8增加了
size类
,它们改变了
UIAlertView
的显示方向。请参阅:

我很恼火,因为我一直在写这两种情况,所以我写了一个兼容的UIAlertController,它也适用于iOS 7,所以我把它放到GitHub上。我尽了最大努力复制添加UIAlertController按钮和操作的方法(更好)。与Objective-C和Swift一起工作。我在谷歌上搜索时发现了这个问题,并认为这可能对其他人有所帮助


从此服务器下载警报类 并且可以轻松地在ios 6、7和8上使用它

//Old code  
**UIAlertView** *alert=[[**UIAlertView** alloc]initWithTitle:@"FreeWare" message:@"Welcome to Common class" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"Ok", nil];

//New code 

**MyAlertView** *alert=[[**MyAlertView** alloc]initWithTitle:@"FreeWare" message:@"Welcome to Common class" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"Ok", nil];

以下是我的拖放swift解决方案:

//Alerts change in iOS8, this method is to cover iOS7 devices
func CozAlert(title: String, message: String, action: String, sender: UIViewController){

    if respondsToSelector("UIAlertController"){
        var alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.Alert)
        alert.addAction(UIAlertAction(title: action, style: UIAlertActionStyle.Default, handler:nil))
        sender.presentViewController(alert, animated: true, completion: nil)
    }
    else {
        var alert = UIAlertView(title: title, message: message, delegate: sender, cancelButtonTitle:action)
        alert.show()
    }
}
这样称呼:

CozAlert("reportTitle", message: "reportText", action: "reportButton", sender: self)

请注意,这仅适用于最基本的警报,您可能需要额外的高级代码。

如果您如上所述同时使用iOS 7-UIAlertView和iOS 8+UIAlertController,并且希望UIAlertController块调用UIAlertView的委托(例如MyController)alertView:didDismissWithButtonIndex方法继续处理结果,下面是一个如何执行此操作的示例:

if ([UIAlertController class]) {
    MyController * __weak mySelf = self;

    UIAlertController *alertController = [UIAlertController
        alertControllerWithTitle:alertTitle
        message:alertMessage
        preferredStyle:UIAlertControllerStyleAlert];

    UIAlertAction *cancelAction = [UIAlertAction
        actionWithTitle:alertCancel
        style:UIAlertActionStyleCancel
        handler:^(UIAlertAction *action)
            {
            [mySelf alertView:nil didDismissWithButtonIndex:0];
            }
    ];

...
这使用了苹果关于在块中捕捉自我的建议:


当然,此方法假定控制器中只有一个UIAlertView,因此将nil作为其值传递给委托方法。否则,您需要实例化(并标记)一个“假”UIAlertView以传递给alertView:didDismissWithButtonIndex。

如果这是共享代码,并且该代码可能用于iOS 8扩展(其中UIAlertView和UIActionSheet是受限制的API)以及iOS 7,其中UIAlertController不存在,看看:

它是UIAlertController到iOS 7的一个API兼容的后端端口,我承诺使SDK代码在iOS 7和iOS 8扩展中都能安全使用。

Swift 2.0

 if #available(iOS 8.0, *) {

 } else {

 }

这里检查
UIAlertView
和的两种方式

检查1:iOS版本检查类

检查2:检查
UIAlertController
nil,然后检查8.0以下的iOS版本

    if objc_getClass("UIAlertController") != nil {

        // UIALertController
        let alert = UIAlertController(title: "Alert", message: "Alert after 8.0", preferredStyle: .Alert)
        let cancelAction = UIAlertAction(title: "OK", style: .Cancel, handler: nil)
        alert.addAction(cancelAction)
        presentViewController(alert, animated: true, completion: nil)

    }
    else {

        // UIALertView
        UIAlertView(title: "Alert", message: "Alert below iOS V 8.0", delegate: nil, cancelButtonTitle: "OK").show()
    }

试试下面的代码。它适用于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];
}

但我在iOS 8设备上运行时收到以下警告:警告:在演示或取消过程中尝试从视图控制器取消!那么提交一份bug报告?iOS 8是一个测试版,它有漏洞。我(ab)使用UIAlertView作为密码双输入类型,两个编辑框必须匹配。我通过将子视图添加到更大的视图中,然后将该视图添加为警报视图的附件视图来实现这一点。不幸的是,视图的大小被截断,第二个编辑框被完全删除,按钮也被完全删除。@Eric不推荐使用,但仅在文档中,他们故意没有在头文件中将其标记为不推荐使用。通常,苹果这样做意味着他们想要pe
 if #available(iOS 8.0, *) {

 } else {

 }
    if #available(iOS 8.0, *) {

        // UIALertController
        let alert = UIAlertController(title: "Alert", message: "Alert after 8.0", preferredStyle: .Alert)
        let cancelAction = UIAlertAction(title: "OK", style: .Cancel, handler: nil)
        alert.addAction(cancelAction)
        presentViewController(alert, animated: true, completion: nil)
    } else {

        // UIALertView
        UIAlertView(title: "Alert", message: "Alert below iOS V 8.0", delegate: nil, cancelButtonTitle: "OK").show()
    }
    if objc_getClass("UIAlertController") != nil {

        // UIALertController
        let alert = UIAlertController(title: "Alert", message: "Alert after 8.0", preferredStyle: .Alert)
        let cancelAction = UIAlertAction(title: "OK", style: .Cancel, handler: nil)
        alert.addAction(cancelAction)
        presentViewController(alert, animated: true, completion: nil)

    }
    else {

        // UIALertView
        UIAlertView(title: "Alert", message: "Alert below iOS V 8.0", delegate: nil, cancelButtonTitle: "OK").show()
    }
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];
}