回答:
以来modalViewController
のiOS 6で廃止されました、ここで警告なしのiOS 5+とそのコンパイルのために働くのバージョンがあります。
Objective-C:
- (BOOL)isModal {
return self.presentingViewController.presentedViewController == self
|| (self.navigationController != nil && self.navigationController.presentingViewController.presentedViewController == self.navigationController)
|| [self.tabBarController.presentingViewController isKindOfClass:[UITabBarController class]];
}
迅速:
var isModal: Bool {
return self.presentingViewController?.presentedViewController == self
|| (self.navigationController != nil && self.navigationController?.presentingViewController?.presentedViewController == self.navigationController)
|| self.tabBarController?.presentingViewController is UITabBarController
}
フェリペの答えへの帽子のヒント。
nil == nil
ます。が返されるため、両側がnilであるかどうかを確認する必要がありますが、これは目的YES
の結果ではありません。
iOS 6以降をお探しの場合、この回答は非推奨であり、Gabriele Petronellaの回答を確認する必要があります
UIKitにネイティブなプロパティまたはメソッドとして、これを行うためのきちんとした方法はありません。あなたができることは、それがモーダルとして提示されることを確実にするために、コントローラーのいくつかの側面をチェックすることです。
したがって、現在の(以下self
のコードのように表される)コントローラーがモーダルな方法で表示されているかUIViewController
どうかを確認するには、カテゴリー内に以下の関数を持っているか、または(プロジェクトで他のUIKitコントローラーを使用する必要がない場合は、UITableViewController
たとえば、他のコントローラーが継承する基本コントローラー
-(BOOL)isModal {
BOOL isModal = ((self.parentViewController && self.parentViewController.modalViewController == self) ||
//or if I have a navigation controller, check if its parent modal view controller is self navigation controller
( self.navigationController && self.navigationController.parentViewController && self.navigationController.parentViewController.modalViewController == self.navigationController) ||
//or if the parent of my UITabBarController is also a UITabBarController class, then there is no way to do that, except by using a modal presentation
[[[self tabBarController] parentViewController] isKindOfClass:[UITabBarController class]]);
//iOS 5+
if (!isModal && [self respondsToSelector:@selector(presentingViewController)]) {
isModal = ((self.presentingViewController && self.presentingViewController.modalViewController == self) ||
//or if I have a navigation controller, check if its parent modal view controller is self navigation controller
(self.navigationController && self.navigationController.presentingViewController && self.navigationController.presentingViewController.modalViewController == self.navigationController) ||
//or if the parent of my UITabBarController is also a UITabBarController class, then there is no way to do that, except by using a modal presentation
[[[self tabBarController] presentingViewController] isKindOfClass:[UITabBarController class]]);
}
return isModal;
}
編集:UITabBarControllerが使用されているかどうかを確認する最後のチェックを追加し、別のUITabBarControllerをモーダルとして提示しました。
EDIT 2:iOSの5+チェック、追加UIViewController
のためにお答えいたしませんparentViewController
もうし、これにpresentingViewController
代わり。
編集3:念のためhttps://gist.github.com/3174081で要点を作成しました
modalViewController
ドキュメントが使用することを示唆しているのiOS 6のようプロパティが廃止されてpresentedViewController
代わりに。
NSLog(@"%@", self.navigationController.parentViewController)
版画(null)
-理由を教えてください。私のViewControllerは、ストーリーボードのnavControllerを介してモーダルビューコントローラーに接続されています。
.parentViewController
非推奨です.presentingViewController
。代わりに使用する必要があります。
iOS5以降では、UIViewController Class Referenceでわかるように、プロパティ「presentingViewController」から取得できます。
presentingViewControllerこのビューコントローラを提示したビューコントローラ。(読み取り専用)
@property(nonatomic、readonly)UIViewController * presentingViewController
ディスカッション
このメッセージを受け取ったビューコントローラーが別のビューコントローラーによって提示された場合、このプロパティはそれを提示しているビューコントローラーを保持します。ビューコントローラーは表示されないが、その祖先の1つが表示されている場合、このプロパティは最も近い祖先を表示するビューコントローラーを保持します。ビューコントローラーもその祖先も表示されていない場合、このプロパティはnilを保持します。
可用性
のiOS 5.0以降で利用可能。
宣言
UIViewController.hで
presentingViewController
です。祖先を自動的にトラバースするため、コンテナビューコントローラでも機能します。
ない場合はpresentedAsModal
、UIViewControllerサブクラスでthis()のプロパティを定義YES
し、ViewControllerをモーダルビューとして表示する前に設定できます。
childVC.presentedAsModal = YES;
[parentVC presentModalViewController:childVC animated:YES];
この値はviewWillAppear
オーバーライドで確認できます。
ビューの表示方法を示す公式のプロパティは存在しないと思いますが、独自のビューを作成することを妨げるものは何もありません。
UINavigationController
モーダルとして表示している場合、このソリューションは機能しません...このプロパティを追加するためだけにカスタムナビゲーションコントローラーを作成する場合を除きます。その後、コントローラー内ではself.navigationController
、コントローラーがモーダルとして表示されているかどうかを確認する必要があるたびに、このカスタムクラスにキャストし続ける必要があります
self.navigationControllerがモーダルに提示されているが、selfがself.navigationController.viewControllers [0]と等しくない場合、ペトロネラの答えは機能しません。その場合、selfがプッシュされます。
これが問題を修正する方法です。
return self.presentingViewController.presentedViewController == self
|| (self.navigationController != nil && self.navigationController.presentingViewController.presentedViewController == self.navigationController && self == self.navigationController.viewControllers[0])
|| [self.tabBarController.presentingViewController isKindOfClass:[UITabBarController class]];
そしてSwiftでは:
return self.presentingViewController?.presentedViewController == self
|| (self.navigationController != nil && self.navigationController?.presentingViewController?.presentedViewController == self.navigationController && self.navigationController?.viewControllers[0] == self)
|| self.tabBarController?.presentingViewController is UITabBarController
これはうまくいくはずです。
if(self.parentViewController.modalViewController == self)…
UINavigationController
とUITabBarController
ケースを確認するための回答を追加しました。これまでのところ、順調に機能しています
全画面のモーダルビューと非モーダルビューを区別する必要がない場合(私のプロジェクトの場合(フォームシートとページシートでのみ発生する問題を扱っていました))、modalPresentationStyleを使用できます。 UIViewControllerのプロパティ:
switch (self.modalPresentationStyle) {
case 0: NSLog(@"full screen, or not modal"); break;
case 1: NSLog(@"page sheet"); break;
case 2: NSLog(@"form sheet"); break;
}
ではスウィフト:
func isUIViewControllerPresentedAsModal() -> Bool {
if((self.presentingViewController) != nil) {
return true
}
if(self.presentingViewController?.presentedViewController == self) {
return true
}
if(self.navigationController?.presentingViewController?.presentedViewController == self.navigationController) {
return true
}
if((self.tabBarController?.presentingViewController?.isKindOfClass(UITabBarController)) != nil) {
return true
}
return false
}
私のプロジェクトには、マスタービューコントローラーによってモーダル(新しいアイテムを追加する場合)またはプッシュ(既存のアイテムを編集する場合)で表示できるビューコントローラー(詳細)があります。ユーザーが[完了]をタップすると、詳細ビューコントローラーはマスタービューコントローラーのメソッドを呼び出して、閉じる準備ができたことを通知します。マスターは、それを閉じる方法を知るために、詳細がどのように提示されるかを決定する必要があります。これは私がこれを行う方法です:
UIViewController *vc = self.navigationController.viewControllers.lastObject;
if (vc == self) {
[self dismissViewControllerAnimated:YES completion:NULL];
} else {
[self.navigationController popViewControllerAnimated:YES];
}
このようなハックはうまくいくかもしれません。
UIViewController* child = self;
UIViewController* parent = child.parentViewController;
while (parent && parent.modalViewController != child) {
child = parent;
parent = child.parentViewController;
}
if (parent) {
// A view controller in the hierarchy was presented as a modal view controller
}
しかし、私の以前の答えはより明確な解決策だと思います。
私のために働いたのは以下の通りです:
// this is the trick: set parent view controller as application's window root view controller
UIApplication.sharedApplication.delegate.window.rootViewController = viewController;
// assert no modal view is presented
XCTAssertNil(viewController.presentedViewController);
// simulate button tap which shows modal view controller
[viewController.deleteButton sendActionsForControlEvents:UIControlEventTouchUpInside];
// assert that modal view controller is presented
XCTAssertEqualObjects(viewController.presentedViewController.class, MyModalViewController.class);
私がテストした限り、これはiOS7とiOS8で動作します。ただし、iOS6は試しませんでした。
私はこの質問に対する正しい答えを見つけるために少し調べましたが、考えられるすべてのシナリオをカバーするものは見つかりませんでした。私は仕事をしているように見えるこれらの数行のコードを書きました。何がチェックされているかを理解するために、いくつかのインラインコメントを見つけることができます。
- (BOOL)isModal {
BOOL modal = NO;
if ([self presentingViewController]) { //Some view Controller is presenting the current stack
UIViewController *presented = [[self presentingViewController] presentedViewController]; // What's been presented
if ([presented respondsToSelector:@selector(viewControllers)]) { // There's a stack
NSArray *viewControllers = [presented performSelector:@selector(viewControllers)];
modal = [viewControllers firstObject] == self; // Current VC is presented modally if it's the first in the stack
}
else {
modal = presented == self; // Don't think this is actually needed. set modal = YES should do the job tho.
}
}
return modal;
}
この助けを願っています。
isModal
@GabrielePetronellaの変更バージョンは次のとおりです。これは、最初にparentViewController階層を上に移動するという点で、含まれているビューコントローラーで動作します。また、コードを複数行に引き出して、何をしているのかを明確にしました。
var isModal: Bool {
// If we are a child view controller, we need to check our parent's presentation
// rather than our own. So walk up the chain until we don't see any parentViewControllers
var potentiallyPresentedViewController : UIViewController = self
while (potentiallyPresentedViewController.parentViewController != nil) {
potentiallyPresentedViewController = potentiallyPresentedViewController.parentViewController!
}
if self.presentingViewController?.presentedViewController == potentiallyPresentedViewController {
return true
}
if let navigationController = potentiallyPresentedViewController.navigationController {
if navigationController.presentingViewController?.presentedViewController == navigationController {
return true
}
}
return potentiallyPresentedViewController.tabBarController?.presentingViewController is UITabBarController
}