【问题标题】:How do I migrate from UIAlertView (deprecated in iOS8)如何从 UIAlertView 迁移(在 iOS8 中已弃用)
【发布时间】:2015-06-19 08:55:51
【问题描述】:

我目前在我的一个应用程序中有以下代码行。这是一个简单的UIAlertView。但是,从 iOS 8 开始,现在已弃用:

let alertView = UIAlertView(title: "Oops!", message: "This feature isn't available right now", delegate: self, cancelButtonTitle: "OK")

如何更新它以使用 iOS 8+?我相信我必须将某些内容更改为 UIAlertCotroller,尽管我不太确定是什么。

【问题讨论】:

  • 使用UIAlertController
  • 这不是很有帮助,你能解释一下如何使用 UIAlertController。这不仅仅是将单词视图换成控制器的情况
  • @Bhavin 每个框架都会发生这种情况。旧的 API 有时必须被更好的 API 替换。这不像UIAlert 现在正在被删除。在它被完全删除之前,我们仍然会保留它的几个版本。

标签: ios xcode swift swift2 xcode7


【解决方案1】:

您需要改用UIAlertController。致class documentation 非常简单,甚至在文档开头的清单 1 中包含一个用法示例(确保它是在 ObjC 中而不是在 Swift 中,但它非常相似)。

因此,对于您的用例,以下是它的转换方式(添加了 cmets):

let alert = UIAlertController(title: "Oops!", message:"This feature isn't available right now", preferredStyle: .alert)
let action = UIAlertAction(title: "OK", style: .default) { _ in
  // Put here any code that you would like to execute when
  // the user taps that OK button (may be empty in your case if that's just
  // an informative alert)
}
alert.addAction(action)
self.presentViewController(alert, animated: true){}

所以紧凑的代码如下所示:

let alert = UIAlertController(title: "Oops!", message:"This feature isn't available right now", preferredStyle: .Alert)
alert.addAction(UIAlertAction(title: "OK", style: .Default) { _ in })
self.present(alert, animated: true){}

这里的self 应该是你的UIViewController


附加提示:如果您需要调用在UIViewController 上下文之外显示警报的代码(其中self 不是UIViewController),您始终可以使用应用程序的根VC:

let rootVC = UIApplication.sharedApplication().keyWindow?.rootViewController
rootVC?.presentViewController(alert, animated: true){}

(但一般来说,当你有一个 UIViewController 时最好使用已知的UIViewController——无论如何你通常都会从 UIViewControllers 发出警报——或者尝试根据你的上下文获得最合适的一个,而不是依赖这个提示)

【讨论】:

  • 当然不是,因为UIAlertController是在iOS8中引入的。
  • @AiSoftware 那么,也许这不是一个迁移的好方法。它会拒绝您当前用户的更新,并从仍在使用 iOS ≤ 7 的潜在用户那里窃取应用程序。
  • 你是什么意思“它会拒绝iOS≤7用户的更新”? (1) 如果您的应用程序是用 Swift 编写的,就像 OP 的代码一样,它无论如何都不会在 iOS if #available(iOS 8.0) 在 Swift 中,if ([UIAlertController class]) 在 Objective -C)... 如果它不可用,则回退到UIAlertView — 这就是我们在使用新 API 时总是做的,如 Apple 的“SDK 兼容性指南”中所述(以及在仍然需要支持旧操作系统版本时应该如何迁移) ,所以这里没有什么新东西)。
  • 有关支持多个操作系统版本的更多信息,您可以在this Apple doc 中找到很多有用的信息。简而言之,您可以在用户运行 iOS8 时使用UIAlertController,并且在这种情况下通过使用 UIAlertViewController 作为后备来仍然与 iOS7 兼容。
  • 用 Swift 编写,你正在编写一个 iOS 8 应用程序,其中 UIAlertView 已经被弃用并且 UIAlertController 已经存在,所以没有迁移问题,因为你从新的开始。这个问题是How do I migrate from UIAlertView (deprecated in iOS8),这意味着该应用程序已经足够老,可以在 iOS 7 中使用 UIAlertView,但现在正在迁移到 iOS 8。我不知道 OP 是如何在 Swift 应用程序上发现自己处于这种情况的,但这没有实际意义.
【解决方案2】:

对于那些想知道如何在 Objective-C 中做到这一点的人:

    //Step 1: Create a UIAlertController
    UIAlertController *myAlertController = [UIAlertController alertControllerWithTitle:@"MyTitle"
                                                              message: @"MyMessage"
                                                              preferredStyle:UIAlertControllerStyleAlert                   ];

    //Step 2: Create a UIAlertAction that can be added to the alert
    UIAlertAction* ok = [UIAlertAction
                         actionWithTitle:@"OK"
                         style:UIAlertActionStyleDefault
                         handler:^(UIAlertAction * action)
                         {
                             //Do some thing here, eg dismiss the alertwindow
                             [myAlertController dismissViewControllerAnimated:YES completion:nil];

                         }];

    //Step 3: Add the UIAlertAction ok that we just created to our AlertController
    [myAlertController addAction: ok];

    //Step 4: Present the alert to the user
    [self presentViewController:myAlertController animated:YES completion:nil];

这将弹出一个如下所示的警报:

【讨论】:

  • 这对于 Objective C 来说是一个很好的答案,但不需要在处理程序中关闭警报。这是自动完成的。
  • 这是一个很好的答案,但我们如何处理处理程序?我不想使用嵌入式 lambda,而是多个 alertAction 共有的外部函数
【解决方案3】:
let alertView = UIAlertView(title: "Oops!", message: "This feature isn't available right now", delegate: self, cancelButtonTitle: "OK")

变成

let alertController = UIAlertController(title: "Oops!", message: "This feature isn't available right now", preferredStyle: .Alert)
let OKAction = UIAlertAction(title: "OK", style: .Default) { (action) in }
alertController.addAction(OKAction)
self.presentViewController(alertController, animated: true) { }

【讨论】:

    【解决方案4】:

    我认为这是向后兼容旧 iOS SDK 并在使用新 SDK 时使用新 API 的方法。此外,使用已弃用的类在代码中弃用也没有警告。

        if ([UIAlertController class]) {
            // Use new API to create alert controller, add action button and display it
            UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"CityBoard" message:error.errorDescription preferredStyle:UIAlertControllerStyleAlert];
            UIAlertAction* ok = [UIAlertAction actionWithTitle: @"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
                [alertController dismissViewControllerAnimated:YES completion:nil];
            }];
            [alertController addAction: ok];
            [self presentViewController:alertController animated:YES completion:nil];
        } else {
            // We are running on old SDK as the new class is not available
            // Hide the compiler errors about deprecation and use the class available on older SDK
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Wdeprecated-declarations"
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"CityBoard"
                                                            message:error.errorDescription
                                                           delegate:self
                                                  cancelButtonTitle:@"OK"
                                                  otherButtonTitles:nil];
            [alert show];
    #pragma clang diagnostic pop
    

    【讨论】:

      【解决方案5】:

      Swift 2.0:

      使用警报控制器。

      操作表示例:

        let mediaActionSheet: UIAlertController = UIAlertController(title: "Media Action Sheet", message: "Choose an option!", preferredStyle: .ActionSheet)
      
        //Create and add the Cancel action
        let cancelAction: UIAlertAction = UIAlertAction(title: "Cancel", style: .Cancel) { action -> Void in
      
         //Just dismiss the action sheet
      
        }
        mediaActionSheet.addAction(cancelAction)
        //Create and add first option action
        let takePictureAction: UIAlertAction = UIAlertAction(title: "Take Picture", style: .Default) { action -> Void in
      
         //Code for launching the camera goes here
      
        }
      
        mediaActionSheet.addAction(takePictureAction)
      
        //Create and add a second option action
        let choosePictureAction: UIAlertAction = UIAlertAction(title: "Choose From Gallery", style: .Default) { action -> Void in
      
         //Code for picking from gallery goes here
      
        }
      
        mediaActionSheet.addAction(choosePictureAction)
      
        //Present the AlertController
        self.presentViewController(mediaActionSheet, animated: true, completion: nil)
      

      警报示例:

      1)

      let simpleAlert = UIAlertController(title: "Simple Alert", message: "It is just awesome", preferredStyle: UIAlertControllerStyle.Alert);
      
        //show it
        showViewController(simpleAlert, sender: self);
      

      2) 带有 TextField 的警报。

        let inputTextFieldAlert:UIAlertController = UIAlertController(title: " Input TextField Alert ", message: " Enter on the below TextField ", preferredStyle: UIAlertControllerStyle.Alert);
      
        //default input textField (no configuration...)
        inputTextFieldAlert.addTextFieldWithConfigurationHandler(nil);
      
        //no event handler (just close dialog box)
        inputTextFieldAlert.addAction(UIAlertAction(title: "No", style: UIAlertActionStyle.Cancel, handler: nil));
      
        //event handler with closure
        inputTextFieldAlert.addAction(UIAlertAction(title: "Yes", style: UIAlertActionStyle.Default, handler: {(action:UIAlertAction) in
      
         let fields = inputTextFieldAlert.textFields!;
         print("Output: "+fields[0].text!);
        }));
      
        presentViewController(inputTextFieldAlert, animated: true, completion: nil);
      

      3)

      var alert = UIAlertController(title: "TextField Alert", message: "Enter on the below TextField", preferredStyle: UIAlertControllerStyle.Alert);
      
        //configured input textField
        var field:UITextField?;
      
        alert.addTextFieldWithConfigurationHandler({(input:UITextField)in
         input.placeholder="Empty Dtaa ;-)";
         input.clearButtonMode=UITextFieldViewMode.WhileEditing;
      
         field=input;
        });
      
        //YES Handler
        func yesHandler(actionTarget: UIAlertAction){
      
         print(field!.text!);
        }
        //event handler with predefined function
        alert.addAction(UIAlertAction(title: "Yes", style: UIAlertActionStyle.Default, handler: yesHandler));
      
        presentViewController(alert, animated: true, completion: nil);
      

      【讨论】:

      • 如果你想这样做: let simpleAlert = UIAlertController(title: "Simple Alert", message: "You selected row %ld from list", preferredStyle: UIAlertControllerStyle.Alert);您想在哪里用值替换 %ld?
      【解决方案6】:

      上面的例子对我帮助不大。我的解决方案适用于 XCode 6.4.、Swift 1.2,您可以将此代码复制并粘贴到测试项目中以了解其工作原理:

      解决方案 1 - Swift 1.2:

      import UIKit
      
      let ALERT_TITLE   = "Got you working, right?"
      let ALERT_MESSAGE = "Well maybe..."
      
      class ViewController: UIViewController
      {
          private var alert: UIAlertController!
      
          private var presentAlertButton: UIButton!
      
          override func viewDidAppear(animated: Bool)
          {
              /*
              // QUICK TEST - 1
              self.presentViewController(alert, animated: true, completion: nil)
              */
      
      
              // QUCIK TEST - 2
              /*
              let rootVC = UIApplication.sharedApplication().keyWindow?.rootViewController
              rootVC?.presentViewController(alert, animated: true, completion: nil)
              */
          }
      
          override func viewDidLoad()
          {
              super.viewDidLoad()
      
              createAndAddAlertV()
      
              createAndAddAlertButton()
          }
      
          private func createAndAddAlertV()
          {
              alert = UIAlertController(title:ALERT_TITLE, message:ALERT_MESSAGE, preferredStyle: .Alert)
              let alertAction = UIAlertAction(title: "OK", style: .Default, handler: nil)
              alert.addAction(alertAction)
          }
      
          private func createAndAddAlertButton()
          {
              presentAlertButton = UIButton(frame: CGRectMake(
                  view.frame.size.width / 2,
                  view.frame.size.height / 2,
                  200,
                  100))
      
              presentAlertButton.layer.anchorPoint = CGPointMake(1.0, 1.0)
              presentAlertButton.backgroundColor = UIColor.redColor()
              presentAlertButton.setTitle("Click For Alert", forState: .Normal)
              presentAlertButton.addTarget(self, action: "showAlertV", forControlEvents: .TouchUpInside)
              self.view.addSubview(presentAlertButton)
          }
      
          @IBAction func showAlertV()
          {
              println(" Showing... ")
              self.presentViewController(alert, animated: true, completion: nil)
          }
      
      }
      

      我在 Xcode 7.0 中检查了这个解决方案。有效。 Xcode 进行了一项更改。我再次在 Xcode 6.4 中重新编译它并且它工作。 Swift 2.0 的变化应该是很小的,如果存在的话。

      希望这会有所帮助;)

      【讨论】:

        【解决方案7】:

        您可以将此代码用于警报视图:

         UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Title" message:@"Message" preferredStyle:UIAlertControllerStyleAlert];
        
                UIAlertAction* ok = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil];
                [alertController addAction:ok];
        
                [self presentViewController:alertController animated:YES completion:nil];
        

        您可以使用多个按钮:

         UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Title" message:@"Message" preferredStyle:UIAlertControllerStyleAlert];
        
                [alertController addAction:[UIAlertAction actionWithTitle:@"Button 1" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
                    [self loadGooglrDrive];
                }]];
        
                [alertController addAction:[UIAlertAction actionWithTitle:@"Button 2" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
                    [self loadDropBox];
                }]];
        
                [alertController addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
                    [self closeAlertview];
                }]];
        
                dispatch_async(dispatch_get_main_queue(), ^ {
                    [self presentViewController:alertController animated:YES completion:nil];
                });
        
        -(void)closeAlertview
        {
        
            [self dismissViewControllerAnimated:YES completion:nil];
        }
        

        【讨论】:

          【解决方案8】:

          https://github.com/nagibazad/UIAlertControllerWrapper

          这个包装器提供了一种将 UIAlertView 轻松转换为 UIAlertController 的方法。 UIAlertView 已从 iOS 9.0 弃用。将旧项目的UIAlertView 转换为UIAlertController,使用此UIAlertControllerWrapper 保持您的委托实现保持不变,并删除所有与UIAlertView 相关的warnings

          【讨论】:

            猜你喜欢
            • 2016-01-14
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-01-31
            • 2015-02-18
            • 1970-01-01
            • 2016-01-17
            • 2021-10-15
            相关资源
            最近更新 更多