在ViewController类内部,有没有可能检查它是作为模态视图控制器呈现的?
在ViewController类内部,有没有可能检查它是作为模态视图控制器呈现的?
自从iOS 6中modalViewController
被弃用后,这里提供了一个适用于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]];
}
Swift:
var isModal: Bool {
return self.presentingViewController?.presentedViewController == self
|| (self.navigationController != nil && self.navigationController?.presentingViewController?.presentedViewController == self.navigationController)
|| self.tabBarController?.presentingViewController is UITabBarController
}
向Felipe的答案致敬。
如果你正在寻找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作为模态呈现。
编辑2:添加了iOS 5+检查,其中UIViewController
不再为parentViewController
回答,而是改为回答presentingViewController
。
编辑3:我已经创建了一个Gist备用,以防万一https://gist.github.com/3174081
modalViewController
属性已在iOS 6中被弃用。文档建议使用presentedViewController
替代。 - Bart JacobsNSLog(@"%@", self.navigationController.parentViewController)
打印出 (null)
- 你能解释一下为什么吗?我的 ViewController 通过 storyboard 中的 navController 与模态视图控制器相连接。 - Roman.parentViewController
已经被弃用,必须使用 .presentingViewController
代替。 - RomaniOS 5+
回退和presentingViewController
逻辑...难道它在你遇到的某些特定情况下无法工作吗? - Felipe SabinoiOS5+ 中,可以从属性 "presentingViewController" 获取“UIViewController Class Reference”中所述的内容。详情请参见 UIViewController 类的参考资料。
presentingViewController 呈现此视图控制器的视图控制器。(只读)
@property(nonatomic, readonly) UIViewController *presentingViewController
Discussion
如果接收此消息的视图控制器由另一个视图控制器呈现,则此属性保存呈现它的视图控制器。如果当前视图控制器未被呈现,但其祖先之一正在被呈现,则此属性保存最近的祖先视图控制器。如果既未呈现当前视图控制器也未呈现任何祖先视图控制器,则此属性保存 nil。
Availability
iOS 5.0 及更高版本可用。
Declared In
UIViewController.h
childVC.presentedAsModal = YES;
[parentVC presentModalViewController:childVC animated:YES];
您可以在viewWillAppear
重写方法中检查此值。
我相信没有官方属性来表示视图的呈现方式,但是没有任何阻止您创建自己的属性。
UINavigationController
作为模态呈现,则此解决方案无效...除非您创建一个自定义导航控制器来添加此属性。之后,在控制器内部,每次需要检查控制器是否以模态方式呈现时,都必须将self.navigationController
强制转换为此自定义类。 - Felipe Sabinoreturn 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
两种情况。目前它运行得非常好。 - Felipe Sabino检查的最佳方法
if (self.navigationController.presentingViewController) {
NSLog(@"Model Present");
}
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的modalPresentationStyle属性:
switch (self.modalPresentationStyle) {
case 0: NSLog(@"full screen, or not modal"); break;
case 1: NSLog(@"page sheet"); break;
case 2: NSLog(@"form sheet"); break;
}
UIViewController *vc = self.navigationController.viewControllers.lastObject;
if (vc == self) {
[self dismissViewControllerAnimated:YES completion:NULL];
} else {
[self.navigationController popViewControllerAnimated:YES];
}
nil == nil
返回YES
,这不是我们想要的结果。 - CocoaBob