Search code examples
objective-cuialertviewuialertcontrollerpresentviewcontroller

Get presentViewController from non view class (Objective-C)


I am trying to replace a call to the deprecated UIAlertView with UIAlertController. The class that displays the alert isn’t a view controller, so I’m unsure what to use in place of the “self presentViewController”.

For background, this is how I was displaying the alert using UIAlertView:

UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Title" message:@"Message" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alert show];

And this was my intended replacement using UIAlertController:

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

However, as mentioned, I can’t use “self presentViewController” from this location, so I tried to get (and use) the view controller like this:

UIViewController *viewController = [UIApplication sharedApplication].keyWindow.rootViewController;
[viewController presetViewController:alert animated:YES completion:nil];

The above code results in the compilation error, “No visible @interface for 'UIViewController' declares the selector 'presetViewController:animated:completion:'”.

How should I resolve this?

Thanks!

PS: It’s obvious without my saying it, but I’m an Objective-C novice. I’ve spent 20+ years writing c++ on that other OS…


Solution

  • This code: [viewController:alert animated:YES completion:nil]; is incorrect. It should be [viewController presentViewController:alert animated:YES completion:nil];.

    With that said, you'll also want to make sure you're presenting the alert from the current view controller on screen. This will work fine if you only ever have one view controller, but if you've presented another view controller on top of your root vc (or 2, or 10), you'll want to get that presented vc and have that vc present the alert.

    Here's an example:

    + (UIViewController*)getActiveViewController
    {
        UIViewController* vc = [[UIApplication sharedApplication] delegate].window.rootViewController;
        while(vc.presentedViewController)
        {
            vc = vc.presentedViewController;
        }
    
        return vc;
    }