2013-04-12 4 views
18

可視のビューコントローラビューが何であるかを知らなくても、ビューコントローラをモーダルに表示する方法はありますか?基本的には、どのような時点でもアラートビューを表示するように並べ替えます。現在のビューコントローラを知らずにモーダルコントローラを表示していますか?

私はのような何かをできるようにしたいと思います:

MyViewController *myVC = [[MyViewController alloc] init]; 
[myVC showModally]; 
私はアプリ内のどこからこれを呼び出すことができるようにしたいのですが、それが一番上に表示されている

。私は現在のビューコントローラが何であるか気にしたくありません。

これを使用してログインプロンプトを表示する予定です。私はアラートビューを使用したくないし、アプリケーション全体でログインプレゼンテーションコードを使用したくない。

これについてのご意見はありますか?それともこれを達成するためのより良い方法がありますか?私はちょうど私自身の仕組みを実装し、ウィンドウの上にビューを置くだけでいいですか?

あなたはこのコードはアプリのデリゲートに実装されている可能性が
+0

あなたはストーリーボードを使用しない場合はnilを返すようにelse ifケースを追加する必要がありますか? –

+0

@SpaceDust nope – nebs

答えて

27

さて、チェーンをたどることができます。

[UIApplication sharedApplication].delegate.window.rootViewControllerから開始してください。

各ビューコントローラで、次の一連のテストを実行します。

[viewController isKindOfClass:[UINavigationController class]]の場合は、[(UINavigationController *)viewController topViewController]に進みます。

[viewController isKindOfClass:[UITabBarController class]]の場合は、[(UITabBarController *)viewController selectedViewController]に進みます。

[viewController presentedViewController]の場合は[viewController presentedViewController]に進みます。

+3

これは最も正しい答えです。 –

+1

アイデアを使って再帰的メソッドを作成しました:https://gist.github.com/MartinMoizard/6537467魅力のように動作します:) – MartinMoizard

+0

これは正解です。 –

7

:どこ

から

AppDelegate.m

-(void)presentViewControllerFromVisibleController:(UIViewController *)toPresent 
{ 
    UIViewController *vc = self.window.rootViewController; 
    [vc presentViewController:toPresent animated:YES]; 
} 

AppDelegate.h

-(void)presentViewControllerFromVisibleViewController:(UIViewController *)toPresent; 

#import "AppDelegate.h" ... AppDelegate *delegate = [UIApplication sharedApplication].delegate; [delegate presentViewControllerFromVisibleViewController:myViewControllerToPresent]; 

あなたの代理人は、windowrootViewControllerを取得しています。これは常に可視になります。それはすべての親のコントローラです。

+7

これは通常動作しますが、ルートビューコントローラが常に表示されるのは間違いです。画面上にモーダルビューコントローラが存在する可能性があります。そのような状況下でこのコードを実行するとどうなるかわかりません。 – rdelmar

+0

@rdelmarその場合、ルートVCはモーダルVCを提示しているルートになります。 – Undo

+4

ええ、それはまだ根ですが動作しません - モーダルビューコントローラが画面上にあり、ルートVCから別のコントローラを表示しようとすると警告が表示され、コントローラが表示されません(試行のビューをウィンドウ階層に表示しないでください)。 – rdelmar

2

どのView Controllerが表示されているかを必ずしも知る必要はないと思います。アプリケーションのkeyWindowにアクセスし、モーダルビューコントローラのビューをビューのリストの先頭に追加することができます。その後、UIAlertViewのように動作させることができます。

インタフェースファイル: MyModalViewController.h

#import <UIKit/UIKit.h> 

@interface MyModalViewController : UIViewController 
- (void) show; 
@end 

実装ファイル: MyModalViewController。あなたはそれから提示する前に、特別な条件を扱うことができるようにメートル

#import "MyModalViewController.h" 


@implementation MyModalViewController 

- (void) show { 
    UIWindow *window = [[UIApplication sharedApplication] keyWindow]; 
    // Configure the frame of your modal's view. 
    [window addSubview: self.view]; 
} 

@end 
19

スウィフトで私のソリューション(MartinMoizardの要旨に触発さ)

extension UIViewController { 
    func presentViewControllerFromVisibleViewController(_ viewControllerToPresent: UIViewController, animated flag: Bool, completion: (() -> Void)?) { 
     if let navigationController = self as? UINavigationController { 
      navigationController.topViewController?.presentViewControllerFromVisibleViewController(viewControllerToPresent, animated: flag, completion: completion) 
     } else if let tabBarController = self as? UITabBarController { 
      tabBarController.selectedViewController?.presentViewControllerFromVisibleViewController(viewControllerToPresent, animated: flag, completion: completion) 
     } else if let presentedViewController = presentedViewController { 
      presentedViewController.presentViewControllerFromVisibleViewController(viewControllerToPresent, animated: flag, completion: completion) 
     } else { 
      present(viewControllerToPresent, animated: flag, completion: completion) 
     } 
    } 
} 
5

このソリューションは、あなたの一番上のビューコントローラを提供します。たとえば、一番上のビューコントローラが特定のビューコントローラでない場合にのみ、ビューコントローラを表示することができます。これにより

extension UIApplication { 
    /// The top most view controller 
    static var topMostViewController: UIViewController? { 
     return UIApplication.shared.keyWindow?.rootViewController?.visibleViewController 
    } 
} 

extension UIViewController { 
    /// The visible view controller from a given view controller 
    var visibleViewController: UIViewController? { 
     if let navigationController = self as? UINavigationController { 
      return navigationController.topViewController?.visibleViewController 
     } else if let tabBarController = self as? UITabBarController { 
      return tabBarController.selectedViewController?.visibleViewController 
     } else if let presentedViewController = presentedViewController { 
      return presentedViewController.visibleViewController 
     } else { 
      return self 
     } 
    } 
} 

あなたは一番上のビューコントローラがない場合にのみ、最上位のView Controllerが

UIApplication.topMostViewController?.present(viewController, animated: true, completion: nil) 

が何であるかを知っているか、あなたのビューコントローラを提示することなく、どこからでもあなたのビューコントローラを提示することができます注意すべき特定のビューコントローラ

if let topVC = UIApplication.topMostViewController, !(topVC is FullScreenAlertVC) { 
    topVC.present(viewController, animated: true, completion: nil) 
} 

ことの一つは、現在表示されているUIAlertControllerがありますならば、UIApplication.topMostViewControllerは0123を返すということです。 UIAlertControllerの上に提示することは奇妙な動作をしており、避けるべきです。そのように、あなたは手動で提示する前!(UIApplication.topMostViewController is UIAlertController)いることを確認するか、self is UIAlertController

extension UIViewController { 
    /// The visible view controller from a given view controller 
    var visibleViewController: UIViewController? { 
     if let navigationController = self as? UINavigationController { 
      return navigationController.topViewController?.visibleViewController 
     } else if let tabBarController = self as? UITabBarController { 
      return tabBarController.selectedViewController?.visibleViewController 
     } else if let presentedViewController = presentedViewController { 
      return presentedViewController.visibleViewController 
     } else if self is UIAlertController { 
      return nil 
     } else { 
      return self 
     } 
    } 
} 
関連する問題