Skip to content

Instantly share code, notes, and snippets.

@MartinMoizard
Created September 12, 2013 13:37
Show Gist options
  • Save MartinMoizard/6537467 to your computer and use it in GitHub Desktop.
Save MartinMoizard/6537467 to your computer and use it in GitHub Desktop.
Category on UIViewController: recursive function to present a modal View Controller anywhere in the application. Example: [self.window.rootViewController presentViewControllerFromVisibleViewController:myViewController]; Works with application using only UINavigationController and modal views. Can be enhanced to handle UITabBarController or other…
- (void)presentViewControllerFromVisibleViewController:(UIViewController *)viewControllerToPresent
{
if ([self isKindOfClass:[UINavigationController class]]) {
UINavigationController *navController = (UINavigationController *)self;
[navController.topViewController presentViewControllerFromVisibleViewController:viewControllerToPresent];
} else if (self.presentedViewController) {
[self.presentedViewController presentViewControllerFromVisibleViewController:viewControllerToPresent];
} else {
[self presentModalViewController:viewControllerToPresent animated:YES];
}
}
@allaire
Copy link

allaire commented Mar 10, 2015

Swift equivalent, thanks!

extension UIViewController {

    func presentViewControllerFromVisibleViewController(viewControllerToPresent: UIViewController, animated flag: Bool, completion: (() -> Void)?) {
        if self is UINavigationController {
            let navigationController = self as UINavigationController
            navigationController.topViewController.presentViewControllerFromVisibleViewController(viewControllerToPresent, animated: true, completion: nil)
        } else if (presentedViewController != nil) {
            presentedViewController!.presentViewControllerFromVisibleViewController(viewControllerToPresent, animated: true, completion: nil)
        } else {
            presentViewController(viewControllerToPresent, animated: true, completion: nil)
        }
    }
}

@dkk
Copy link

dkk commented Oct 28, 2015

Corrected for Swift 2.0:

func presentViewControllerFromVisibleViewController(viewControllerToPresent: UIViewController, animated flag: Bool, completion: (() -> Void)? = nil) {
        if let navigationController = self as? UINavigationController, let topViewController = navigationController.topViewController {
            topViewController.presentViewControllerFromVisibleViewController(viewControllerToPresent, animated: true, completion: completion)
        } else if (presentedViewController != nil) {
            presentedViewController!.presentViewControllerFromVisibleViewController(viewControllerToPresent, animated: true, completion: completion)
        } else {
            presentViewController(viewControllerToPresent, animated: true, completion: completion)
        }
    }

@beeradmoore
Copy link

Xamarin.iOS equivalent :)

[Category(typeof(UIViewController))]
public static class UIViewControllerCategory
{
    public static void PresentViewControllerFromVisibleViewController(this UIViewController self, UIViewController viewControllerToPresent)
    {
        if (self.IsKindOfClass(new Class(typeof(UINavigationController))))
        {
            UINavigationController navigationController = (UINavigationController)self;
            navigationController.TopViewController.PresentViewControllerFromVisibleViewController(viewControllerToPresent);
        }
        else if (self.PresentedViewController != null)
        {
            self.PresentedViewController.PresentViewControllerFromVisibleViewController(viewControllerToPresent);
        }
        else
        {
            self.PresentViewController(viewControllerToPresent, true, null);
        }
    }
}

@spencerwhyte
Copy link

spencerwhyte commented Oct 14, 2016

Corrected for Swift 3.0

extension UIViewController{
    func presentViewControllerFromVisibleViewController(viewControllerToPresent: UIViewController, animated flag: Bool, completion: (() -> Void)? = nil) {
        if let navigationController = self as? UINavigationController, let topViewController = navigationController.topViewController {
            topViewController.presentViewControllerFromVisibleViewController(viewControllerToPresent: viewControllerToPresent, animated: true, completion: completion)
        } else if (presentedViewController != nil) {
            presentedViewController!.presentViewControllerFromVisibleViewController(viewControllerToPresent: viewControllerToPresent, animated: true, completion: completion)
        } else {
            present(viewControllerToPresent, animated: true, completion: completion)
        }
    }
}

@anoop4real
Copy link

anoop4real commented Nov 29, 2016

Tried adding support for Tabbar, i tried using it for a subclass of tab bar.....but system couldnt recognize the selector "presentViewControllerFromVisibleViewController", category to viewcontroller is enough to support tabbar also right?

#import "UIViewController+PresentModal.h"

@implementation UIViewController (PresentModal)

- (void)presentViewControllerFromVisibleViewController:(UIViewController *)viewControllerToPresent
{
    if ([self isKindOfClass:[UITabBarController class]]) {
        UITabBarController *tabController = (UITabBarController *)self;
        [tabController.selectedViewController presentViewControllerFromVisibleViewController:viewControllerToPresent]
    }
    else if ([self isKindOfClass:[UINavigationController class]]) {
        UINavigationController *navController = (UINavigationController *)self;
        [navController.topViewController presentViewControllerFromVisibleViewController:viewControllerToPresent];
    } else if (self.presentedViewController) {
        [self.presentedViewController presentViewControllerFromVisibleViewController:viewControllerToPresent];
    } else {
        [self presentModalViewController:viewControllerToPresent animated:YES];
    }
}
@end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment