Display UIAlertController from UIView/NSObject cla

2019-01-14 06:27发布

I have working iOS application In order to support iOS8, I am replacing UIAlertView/UIActionSheet with UIAlertController.

Problem :
For display UIAlertController I need presentViewController method of UIViewController class.
But UIAlertView is display from classes which are inherited from UIView or NSObject,
I can not get [self presentViewController...] method for obvious reason.

My Work :
I tried getting rootViewController form current window and display UIAlertController.

[[[UIApplication sharedApplication] keyWindow].rootViewController presentViewController ...]

but have some rotation problems like if my current view controller do not have rotation support it will rotate if UIAlertController is open.

Question :
Did any one faced same problem and have safe solution ?
if yes please provide me some example or give some guide

10条回答
做自己的国王
2楼-- · 2019-01-14 07:27

In Swift 3:

UIApplication.shared.keyWindow?.rootViewController?.present(alertView, animated: true, completion: nil)
查看更多
我想做一个坏孩纸
3楼-- · 2019-01-14 07:27

For Display UIAlertController in NSObject Class use below Code.

    UIAlertController * popup =   [UIAlertController
                              alertControllerWithTitle:nil
                              message:nil
                              preferredStyle:UIAlertControllerStyleActionSheet];

    UIAlertAction* cancel = [UIAlertAction
                             actionWithTitle:@"Cancel"
                             style:UIAlertActionStyleCancel
                             handler:^(UIAlertAction * action) {
                                 [popup dismissViewControllerAnimated:YES completion:nil];
                             }];
    [popup addAction:cancel];

    UIViewController *rootViewController = [[Helper shareInstance] topViewController];
    [rootViewController presentViewController:popup animated:YES completion:nil];

// Put Below Method in Your Global Helper Class.

- (UIViewController *)topViewController {
  return [self topViewController:[UIApplication sharedApplication].keyWindow.rootViewController];
}

- (UIViewController *)topViewController:(UIViewController *)rootViewController {
    if (rootViewController.presentedViewController == nil) {
        return rootViewController;
    }

    if ([rootViewController.presentedViewController isMemberOfClass:[UINavigationController class]]) {
        UINavigationController *navigationController = (UINavigationController *)rootViewController.presentedViewController;
        UIViewController *lastViewController = [[navigationController viewControllers] lastObject];
        return [self topViewController:lastViewController];
    }

    UIViewController *presentedViewController = (UIViewController *)rootViewController.presentedViewController;
    return [self topViewController:presentedViewController];
}
查看更多
霸刀☆藐视天下
4楼-- · 2019-01-14 07:30

In general, alerts should be handled in the view controller. Here's an example of the code required:

Swift 3

private func displayError(message: String) {
    let alertController = UIAlertController(title: nil, message: message, preferredStyle: .alert)
    let okayAction = UIAlertAction(title: "Okay", style: .default, handler: nil)
    alertController.addAction(okayAction)
    present(alertController, animated: true, completion: nil)
}
查看更多
聊天终结者
5楼-- · 2019-01-14 07:32

I had a situation where a subview contains a button to dismiss it. I present an alert to confirm the action. It sends a message to the delegate - which is the view controller containing the subview - to remove the subview

Originally I presented a UIAlertView from a UIView. Refactoring for UIAlertController, since the UIAlertController can't present itself like a UIAlertView can, I came up with the following (in Swift; easily translated to ObjC):

Add a protocol to the subview:

protocol MySubviewDelegate {

    // called when user taps subview/delete button
    //   or, you could call it from a gesture handler, etc.
    func displayAlert(alert : UIAlertController)

    // called when user confirms delete from the alert controller
    func shouldRemoveSubview(sender : AnyObject)

}

Add a delegate for the subview, and add a handler for the button/gesture tap:

class MySubview : UIView {

    var subviewDelegate : MySubviewDelegate!

    ...

    func handleTap(sender : AnyObject) {

        // set up the alert controller here
        var alert = UIAlertController(title: "Confirm Delete", 
            message: "This action is permanent. Do you wish to continue?", 
            preferredStyle: UIAlertControllerStyle.Alert)

        // Cancel action 
        //   nil handler means "no action if Cancel button selected"
        alert.addAction(UIAlertAction(title: "Cancel",
            style: UIAlertActionStyle.Cancel,
            handler: nil))

        // Confirm action
        alert.addAction(UIAlertAction(title: "Confirm",
            style: UIAlertActionStyle.Default,
            handler: { (action : UIAlertAction!) -> Void in

                // call delegate method to perform confirmed action, - i.e. remove
                self.subviewDelegate.shouldRemoveSubview(self)
        }))

        // call delegate method to display alert controller
        //   send alert object to delegate
        self.subviewDelegate.displayAlert(alert)
    }
}

Set the calling UIViewController as the delegate of the subview, e.g., in its viewDidLoad() method, and include protocol methods:

class viewController : UIViewController, MySubviewDelegate {

    override func viewDidLoad() {

        super.viewDidLoad()

        self.subviewDelegate = self

        ...
    }

    func displayAlert(alert : UIAlertController) {

        presentViewController(alert, animated: true, completion: nil)
    }

    func shouldRemoveSubview(sender : AnyObject) {

        // cast as UIView / MySubview subclass
        var subview = sender as MySubview

       // remove the subview / perform the desired action
       subview.removeFromSuperview()

       ...
    }

  ...
}

This avoids the need to find the topmost view controller, or pass references to view controllers to subviews (other than in an object/delegate relationship).

查看更多
登录 后发表回答