ios 如何使用 UIAlertController 替换 UIActionSheet?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27632614/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 04:07:18  来源:igfitidea点击:

How to use UIAlertController to replace UIActionSheet?

iosobjective-cuialertcontrolleruiactionsheet

提问by Don_Chen

I am maintaining an old iOS project which based on SDK 6.0.

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

A method on this project called

这个项目的一个方法叫做

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

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

is used to show a combo box. To achieve the goal, it used UIActionSheet, which is deprecated on iOS8.

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

My solution is like this:

我的解决方案是这样的:

        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];
        }

Is that a proper solution?

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

This is what I mostly concern about: UIAlertController needs to be added to a UIViewController but I can only get the pointer of the UIView, so I used view.nextResponder to get what I want, but it's that a good way?

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

回答by Kampai

I have used following code to show action sheet using UIAlertViewControllerand it works perfect.

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

Swift

迅速

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)

Objective C

目标 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];
}

Edit:

编辑:

You need to get UIViewControllerobject here. You can set global variable or call a delegate method, or you can use notification to get view controller object in this code.

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

and last line in above code will be like.

上面代码中的最后一行就像。

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

self.viewControlleris a global variable which will be set before you actually get this view.

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

Because the approach you are following now using view.nextResponder. I'm afraid that it may not work.

因为您现在遵循的方法使用view.nextResponder. 恐怕这行不通。

回答by vladicabg

I have used action sheet for changing profile picture. I followed Kampai approach, just removed dismissviewController call since it was kicking me out of a view when pressing Cancel or photo selection view

我已经使用操作表来更改个人资料图片。我遵循了 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];

}]];

回答by Saurabh Yadav

Swift update -

快速更新——

    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)

回答by Sazzad Hissain Khan

Swift 4

斯威夫特 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)

回答by Cynichniy Bandera

While it may look very simple, there is a nasty issue with using UIAlertController. It is memory leaks prone. In order to test if you have the issue, just put a breakpoint at your view controller's deallocmethod and see if it's deallocated properly.

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

I was looking for a solution for quite some time and here is how I use an alert controller in my app.

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

+ (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];
}

This is not all. Here is an example of how you use it in your view controller. In my case its tableviewwith search, so presenting controller may be different.

这还不是全部。这是您如何在视图控制器中使用它的示例。就我而言,它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
                }
         }];
}

回答by Roman Temchenko

You can use view.window.rootViewControllerinstead. If you don't care about presenter it is fine.

你可以view.window.rootViewController改用。如果您不关心演示者,那很好。