How to use UIAlertController to replace UIActionSheet?

Don_Chen picture Don_Chen · Dec 24, 2014 · Viewed 59.1k times · Source

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

A method on this project called

-(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.

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?

Answer

Kampai picture Kampai · Dec 24, 2014

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

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

- (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 UIViewController object here. You can set global variable or call a delegate method, or you can use notification to get view controller object in this code.

and last line in above code will be like.

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

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

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