我创建了一个UIViewController子类,它可以在UINavigationController的导航堆栈中推送,也可以从任何UIViewController呈现(模态)。我需要确定是否显示了我的视图控制器,如果显示,我需要在视图控制器的顶部添加一个带有关闭按钮的工具栏。 (否则,如果将其推入导航堆栈,则会添加默认关闭按钮,使用该用户可以返回。)
在UIViewController子类内部的所有可用版本中说4.3,5.0,直到6.0,如果满足以下条件,我可以假设视图控制器是以模态方式呈现的。
if(self.parentViewController == nil || self.navigationController == nil)
答案 0 :(得分:33)
使用iOS 5,UIViewController获得了一个名为presentingViewController
的只读属性,它替换了parentViewController
的旧语义(现在描述了包含)。当视图控制器需要访问呈现它的视图控制器时,可以使用此属性 - 注意:如果您不熟悉API,这通常会超出您的期望!
此外,引入了isBeingPresented
属性几乎可以解决您当前所处的情况。在视图控制器的viewWillAppear:
中检查此属性。
我认为你似乎也瞄准了iOS 4.3:
在这种情况下,您需要使用isBeingPresented
保护对if ([self respondsToSelector:…])
的调用,然后您可以在else
块中检查parentViewController是否为零。
向后兼容性的另一种方法可能是覆盖+resolveInstanceMethod:
以在运行时为-isBeingPresented
添加实现。这将使您的呼叫站点保持干净,并且只要您放弃古老的iOS支持,就可以摆脱运行时魔术; - )
但是请注意,在iOS< 5:
上运行时,有一些边缘情况,以及初始方法视图控制器可以包含在任何其他视图控制器中 - 包括导航控制器。当最后一种情况发生时,您运气不好:parentViewController
将为nil
,而navigationController
将不。您可以尝试添加大量难以操作的代码来缓解旧iOS中的这种限制......或者您可以放手。
答案 1 :(得分:10)
我使用此代码检查是否显示了UIViewController。
if (uiviewcontroller.presentingViewController != nil) {
// do something
}
答案 2 :(得分:7)
为了处理这种行为,我通常在viewWillAppear / viewWillDisappear方法中设置/重置BOOL切换它。
顺便说一句,您的测试条件似乎不正确。我认为你应该使用
if(self.parentViewController != nil || self.navigationController != nil)
为什么不能一直将工具栏添加到视图控制器中?是否有任何情况下视图已加载但从未显示过?
答案 3 :(得分:7)
我有一个类似的情况,但我提供的视图控制器包装在它自己的导航控制器中。所以在该视图控制器中,当我需要确定是否添加关闭按钮与后退按钮时,我只检查导航控制器堆栈大小。如果显示屏幕,则堆栈大小应为1(需要关闭按钮)...如果使用现有导航控制器推送,则堆栈大小将大于1(需要后退按钮)。
BOOL presented = [[self.navigationController viewControllers] count] == 1;
答案 4 :(得分:3)
@saikamesh。
当您使用UINavigationController导航viewControllers时,我认为您可以使用topViewController
(Doc here)和visibleViewController
(Doc again)来达到您的意图。
你提到:
当它被推入导航堆栈时,则默认关闭按钮 将添加,使用该用户可以返回
如果特定UIViewController的实例很重要,我认为最好创建一个共享单例实例并提供一个全局呈现标志:
id specificVC = [SpecificViewController sharedInstance];
if (specificVC.isPushed) {
[self.navController popToViewController:specificVC animated:YES];
}
并检查是否出现:
if ([self.navController.visibleViewController isKindOfClass:[SpecificViewController class]]) {
// Hide or add close button
self.isPresented = YES;
}
或者,您可以阅读the much accepted answer。
:)希望有所帮助。
答案 5 :(得分:2)
请检查这个方式:
for (UIViewController*vc in [self.navigationController viewControllers]) {
if ([vc isKindOfClass: [OffersViewController class]]){ //this line also checks OffersViewController is presented or not
if(vc.isViewLoaded){
NSLog(@"Yes");
}
}
}
答案 6 :(得分:2)
你可以这样做,它快速而安全
UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;
// Find the top controller on the view hierarchy
while (topController.presentedViewController) {
topController = topController.presentedViewController;
}
// If the top controller it is not already presented
if (![topController isKindOfClass:[YourViewController class]]) {
// Present it
[topController presentViewController:yourViewController animated:YES completion:nil];
}
else {
// do some stuff here
}
答案 7 :(得分:1)
您可以随时使用导航控制器中的modalViewController属性检查是否有模态视图控制器。 例如:
UIViewController *presentedController = self.navigationController.modalViewController;
if (presentedController) {
// At this point, you have a view controller presented from your navigation controller
if ([presentedController isKindOfClass:[controllerYouWantToCheck class]]) {
// add your toolbar/buttons/etc here
}
}
答案 8 :(得分:1)
我在这里没有看到一个优雅的答案:
// Edit: Added 2 other modal cases
extension UIViewController {
var isModal: Bool {
return self.presentingViewController?.presentedViewController == self
|| (navigationController != nil && navigationController?.presentingViewController?.presentedViewController == navigationController)
|| tabBarController?.presentingViewController is UITabBarController
}
}
信用:基于this gist
答案 9 :(得分:1)
在iOS 9(或更高版本)上的Swift中:
if viewController.viewIfLoaded?.window != nil {
// viewController is visible
}
答案 10 :(得分:0)
如果是我,我会有一个自定义初始化方法,并在创建vc时使用它。
vc = [[[MyUIViewControllerSubClass alloc] init] initWithToolbarAndCloseButton:YES];
答案 11 :(得分:0)
在@AmitaiB答案中进行小的修改以创建函数
func isModallyPresented(tmpVC:UIViewController) -> Bool {
return tmpVC.presentingViewController?.presentedViewController == tmpVC
|| (tmpVC.navigationController != nil && tmpVC.navigationController?.presentingViewController?.presentedViewController == tmpVC.navigationController)
|| tmpVC.tabBarController?.presentingViewController is UITabBarController
}
只需通过以下方式进行检查:
if(isModallyPresented(tmpVC:myTopVC)){
//return true if viewcontroller is presented
}
答案 12 :(得分:0)
正如Martin Reed所说,这是最好的方法
BOOL presented = [[self.navigationController viewControllers] count] == 1;
if (presented) {
[self dismissViewControllerAnimated:YES completion:^{
// do whatever you need here
}];
}
else {
[self.navigationController popViewControllerAnimated:YES];
}