【问题标题】:How to use UIAlertController to replace UIActionSheet?如何使用 UIAlertController 替换 UIActionSheet?
【发布时间】:2015-02-22 07:38:59
【问题描述】:

我正在维护一个基于 SDK 6.0 的旧 iOS 项目。

这个项目的一个方法叫做

-(void) showComboBox:(UIView*)view:withOptions:(NSDictionary*)options

用于显示组合框。为了实现这个目标,它使用了 UIActionSheet,它在 iOS8 上已被弃用。

我的解决办法是这样的:

        if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber10_8) {
        UIAlertController* alertController = [UIAlertController 
           alertControllerWithTitle:@"title" 
           message:@"message" 
           preferredStyle:UIAlertControllerStyleActionSheet];

        UIAlertAction* item = [UIAlertAction actionWithTitle:@"item" 
           style:UIAlertActionStyleDefault 
           handler:^(UIAlertAction *action) {
            //do something here 
            //inform the selection to the WebView 
            ...
            [alertController dismissViewControllerAnimated:YES completion:nil];
        }];

        UIAlertAction* cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
            [alertController dismissViewControllerAnimated:YES completion:nil];
        }];

        [alertController addAction:item];
        [alertController addAction:cancelAction];
        //I am not sure whether it's the right way
        if ([view.nextResponder isKindOfClass:UIViewController.class]) {
            UIViewController* vc = (UIViewController*)view.nextResponder;
            [vc presentViewController:alertController animated:YES completion:nil];
        }

这是一个合适的解决方案吗?

这是我最关心的: UIAlertController 需要添加到 UIViewController 但我只能获取 UIView 的指针,所以我使用 view.nextResponder 来获取我想要的,但是这是一个好方法吗?

【问题讨论】:

    标签: ios objective-c uialertcontroller uiactionsheet


    【解决方案1】:

    我已经使用以下代码来显示使用UIAlertViewController 的操作表,并且效果很好。

    斯威夫特

    let alert = UIAlertController(title: "Action Title", message: "Action Message", preferredStyle: .actionSheet)
    let action = UIAlertAction(title: "Item", style: .default) {
        UIAlertAction in
        // Write your code here
    }
    alert.addAction(action)
    
    let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) {
        UIAlertAction in
        // It will dismiss action sheet
    }
    alert.addAction(cancelAction)
    self.present(alert, animated: true, completion: nil)
    

    目标 C

    - (IBAction)buttonClicked:(id)sender {
    
        UIAlertController *actionSheet = [UIAlertController alertControllerWithTitle:@"Action Sheet" message:@"Using the alert controller" preferredStyle:UIAlertControllerStyleActionSheet];
    
        [actionSheet addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
    
            // Cancel button tappped.
            [self dismissViewControllerAnimated:YES completion:^{
            }];
        }]];
    
        [actionSheet addAction:[UIAlertAction actionWithTitle:@"Delete" style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action) {
    
            // Distructive button tapped.
            [self dismissViewControllerAnimated:YES completion:^{
            }];
        }]];
    
        [actionSheet addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
    
            // OK button tapped.
    
            [self dismissViewControllerAnimated:YES completion:^{
            }];
        }]];
    
        // Present action sheet.
        [self presentViewController:actionSheet animated:YES completion:nil];
    }
    

    编辑:

    您需要在此处获取UIViewController 对象。您可以设置全局变量或调用委托方法,也可以在此代码中使用通知获取视图控制器对象。

    上面代码的最后一行会是这样的。

    [self.viewController presentViewController:actionSheet animated:YES completion:nil];
    

    self.viewController 是一个全局变量,将在您实际获得此视图之前设置。

    因为您现在使用的方法是使用view.nextResponder。恐怕它可能不起作用。

    【讨论】:

    • 几乎一样,除了一点点不同:我无法直接获取 UIViewController 的指针,所以我必须使用 UIView.nextResponder 代替,我想知道它是否正确。
    • 您的代码中的view 是什么?它是任何视图控制器的子视图吗?
    • 其实是被WebView用来弹出一个combo box,比如phonegap。
    • 但是无论是设置全局变量还是调用委托方法都意味着很多变化,而且项目看起来很奇怪。为什么使用view.nextResponder 是个坏主意?我已经进行了一些测试,它似乎工作正常。
    • @Kampai 感谢您的回答。它非常简单易懂。它节省了我的时间。
    【解决方案2】:

    虽然看起来很简单,但使用UIAlertController 存在一个令人讨厌的问题。它容易发生内存泄漏。为了测试您是否有问题,只需在视图控制器的dealloc 方法处放置一个断点,然后查看它是否被正确释放。

    我一直在寻找解决方案,下面是我在应用中使用警报控制器的方法。

    + (void)alertWithPresenting:(UIViewController *)presenting title:(NSString *)title
                           text:(NSString *)text buttons:(NSArray *)buttons
                        handler:(void (^)(UIAlertAction *action, NSUInteger index))handler
    {
            UIAlertController *alert = [UIAlertController
                                        alertControllerWithTitle:title message:text
                                        preferredStyle:UIAlertControllerStyleAlert];
            __weak __typeof(alert) weakAlert = alert;
            for (NSString *title in buttons) {
                    UIAlertActionStyle style = UIAlertActionStyleDefault;
                    if ([title isEqualToString:[L10n cancelButton]])
                            style = UIAlertActionStyleCancel;
                    else if ([title isEqualToString:[L10n deleteButton]])
                            style = UIAlertActionStyleDestructive;
                    else if ([title isEqualToString:[L10n archiveButton]])
                            style = UIAlertActionStyleDestructive;
    
                    UIAlertAction *action = [UIAlertAction actionWithTitle:title style:style handler:^(UIAlertAction *action) {
                            if (handler != nil)
                                    handler(action, [buttons indexOfObject:action.title]);
                            [weakAlert dismissViewControllerAnimated:YES completion:nil];
                    }];
                    [alert addAction:action];
            }
            [presenting presentViewController:alert animated:YES completion:nil];
    }
    

    这还不是全部。这是一个如何在视图控制器中使用它的示例。在我的情况下,它的 tableview 带有搜索功能,因此呈现控制器可能会有所不同。

    - (void) deleteCases:(NSArray *)selectedRows
    {
            NSString *text = NSLocalizedStringWithDefaultValue(@"cases.delete.alert.text",
                                                               @"Localizable",  [NSBundle mainBundle],
                                                               @"Deleted cases cannot be restored. Continue with delete?",
                                                               @"Delete alert text");
            NSString *title = NSLocalizedStringWithDefaultValue(@"cases.delete.alert.title",
                                                                @"Localizable",  [NSBundle mainBundle],
                                                                @"Delete cases", @"Detete alert title");
            UIViewController *presenting = self.searchController.active ? self.searchController : self;
            __weak __typeof(presenting) weakPresenting = presenting;
            __weak __typeof(self) weakSelf = self;
            [YourClassName alertWithPresenting:weakPresenting title:title text:text
                                       buttons:@[[L10n deleteButton], [L10n cancelButton]]
                                       handler:^(UIAlertAction *action, NSUInteger index)
            {
                    if (action.style == UIAlertActionStyleDestructive) {
                            __typeof(weakSelf) strongSelf = weakSelf;
                            // Perform your actions using @strongSelf
                    }
             }];
    }
    

    【讨论】:

      【解决方案3】:

      斯威夫特 4

              let alert = UIAlertController(title: "Select One", message: nil, preferredStyle: UIAlertControllerStyle.actionSheet)
              alert.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel, handler: nil))
              alert.addAction(UIAlertAction(title: "Export", style: UIAlertActionStyle.default, handler: { (action) in
      
                  // TODO: Export wordlist
      
              }))
              alert.addAction(UIAlertAction(title: "Import", style: UIAlertActionStyle.default, handler: { (action) in
      
                  // TODO: Import wordlist
              }))
      
              self.present(alert, animated: true, completion: nil)
      

      【讨论】:

        【解决方案4】:

        快速更新 -

            let actionSheet = UIAlertController.init(title: "Please choose a source type", message: nil, preferredStyle: .actionSheet)
            actionSheet.addAction(UIAlertAction.init(title: "Take Photo", style: UIAlertActionStyle.default, handler: { (action) in
                self.openCamera()
            }))
            actionSheet.addAction(UIAlertAction.init(title: "Choose Photo", style: UIAlertActionStyle.default, handler: { (action) in
                self.showPhotoLibrary()
            }))
            actionSheet.addAction(UIAlertAction.init(title: "Cancel", style: UIAlertActionStyle.cancel, handler: { (action) in
                // self.dismissViewControllerAnimated(true, completion: nil) is not needed, this is handled automatically,
                 //Plus whatever method you define here, gets called,
                //If you tap outside the UIAlertController action buttons area, then also this handler gets called.
            }))
            //Present the controller
            self.present(actionSheet, animated: true, completion: nil)
        

        【讨论】:

          【解决方案5】:

          我已使用操作表来更改个人资料图片。我遵循 Kampai 方法,只是删除了 dismissviewController 调用,因为它在按下取消或照片选择视图时将我踢出视图

          UIAlertController *actionSheet = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
          
          [actionSheet addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
          
              // Cancel button tappped do nothing.
          
          }]];
          
          [actionSheet addAction:[UIAlertAction actionWithTitle:@"Take photo" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
          
              // take photo button tapped.
              [self takePhoto];
          
          }]];
          
          [actionSheet addAction:[UIAlertAction actionWithTitle:@"Choose photo" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
          
              // choose photo button tapped.
              [self choosePhoto];
          
          }]];
          
          [actionSheet addAction:[UIAlertAction actionWithTitle:@"Delete Photo" style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action) {
          
              // Distructive button tapped.
              [self deletePhoto];
          
          }]];
          

          【讨论】:

            【解决方案6】:

            您可以改用view.window.rootViewController。如果您不关心主持人,那很好。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2017-06-29
              • 1970-01-01
              • 2014-12-02
              • 1970-01-01
              相关资源
              最近更新 更多