ios - 检查视图控制器是以模态方式呈现还是在导航上推送

在我的视图控制器代码中,我如何区分:

  • 以模态呈现
  • 推送导航堆栈

在两种情况下,HtmlViewControllerUINavigationController都是YES,因此不是很有帮助。

令我感到困惑的是,我的父视图控制器有时是模态的,在其上推送要检查的视图控制器。

事实证明我的问题是我将HtmlViewController嵌入到UINavigationController中,然后呈现。 这就是为什么我自己的尝试和下面的好答案都无效的原因。

HtmlViewController*     termsViewController = [[HtmlViewController alloc] initWithDictionary:dictionary];
UINavigationController* modalViewController;

modalViewController = [[UINavigationController alloc] initWithRootViewController:termsViewController];
modalViewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentViewController:modalViewController
                   animated:YES
                 completion:nil];

我想我最好告诉我的视图控制器它的模态,而不是试图确定。

14个解决方案
113 votes

拿一粒盐,没有测试。

- (BOOL)isModal {
     if([self presentingViewController])
         return YES;
     if([[[self navigationController] presentingViewController] presentedViewController] == [self navigationController])
         return YES;
     if([[[self tabBarController] presentingViewController] isKindOfClass:[UITabBarController class]])
         return YES;

    return NO;
 }
ColdLogic answered 2019-08-18T18:26:24Z
65 votes

你忽略了一种方法:isBeingPresented

isBeingPresented在显示视图控制器时为true,在按下时为false。

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    if ([self isBeingPresented]) {
        // being presented
    } else if ([self isMovingToParentViewController]) {
        // being pushed
    } else {
        // simply showing again because another VC was dismissed
    }
}
rmaddy answered 2019-08-18T18:26:56Z
62 votes

在Swift中:

// MARK: - UIViewController implementation

extension UIViewController {

    var isModal: Bool {

        let presentingIsModal = presentingViewController != nil
        let presentingIsNavigation = navigationController?.presentingViewController?.presentedViewController == navigationController
        let presentingIsTabBar = tabBarController?.presentingViewController is UITabBarController

        return presentingIsModal || presentingIsNavigation || presentingIsTabBar
    }
}
King-Wizard answered 2019-08-18T18:27:16Z
20 votes

self.navigationController!= nil意味着它在导航中   堆。

为了处理在导航控制器以模态方式呈现时按下当前视图控制器的情况,我添加了一些代码行来检查当前视图控制器是否是导航堆栈中的根控制器。

extension UIViewController{
func isModal() -> Bool {

    if let navigationController = self.navigationController{
        if navigationController.viewControllers.first != self{
            return false
        }
    }

    if self.presentingViewController != nil {
        return true
    }

    if self.navigationController?.presentingViewController?.presentedViewController == self.navigationController  {
        return true
    }

    if self.tabBarController?.presentingViewController is UITabBarController {
        return true
    }

    return false
   }
}
Jibeex answered 2019-08-18T18:27:48Z
17 votes

斯威夫特3
这是解决前面回答中提到的问题的解决方案,当isModal()返回true时如果推送UIViewController在呈现的UINavigationController堆栈中。

extension UIViewController {
    var isModal: Bool {
        if let index = navigationController?.viewControllers.index(of: self), index > 0 {
            return false
        } else if presentingViewController != nil {
            return true
        } else if navigationController?.presentingViewController?.presentedViewController == navigationController  {
            return true
        } else if tabBarController?.presentingViewController is UITabBarController {
            return true
        } else {
            return false
        }
    }
}

到目前为止它对我有用。如果进行一些优化,请分享。

Jonauz answered 2019-08-18T18:28:24Z
12 votes

斯威夫特4

var isModal: Bool {
    return presentingViewController != nil ||
           navigationController?.presentingViewController?.presentedViewController === navigationController ||
           tabBarController?.presentingViewController is UITabBarController
}
Charlton Provatas answered 2019-08-18T18:28:44Z
3 votes

正如这里的许多人建议的那样,"检查" 方法不适用于所有情况,在我的项目中,我提出了手动管理的解决方案。关键是,我们通常自己管理演示文稿 - 这不是幕后发生的事情,我们必须反省。

DEViewController文件:

#import <UIKit/UIKit.h>

// it is a base class for all view controllers within a project
@interface DEViewController : UIViewController 

// specify a way viewcontroller, is presented  by another viewcontroller
// the presented view controller should manually assign the value to it
typedef NS_ENUM(NSUInteger, SSViewControllerPresentationMethod) {
    SSViewControllerPresentationMethodUnspecified = 0,
    SSViewControllerPresentationMethodPush,
    SSViewControllerPresentationMethodModal,
};
@property (nonatomic) SSViewControllerPresentationMethod viewControllerPresentationMethod;

// other properties/methods...
@end

现在可以通过这种方式管理演示文稿:

推送导航堆栈:

// DETestViewController inherits from DEViewController
DETestViewController *vc = [DETestViewController new];
vc.viewControllerPresentationMethod = SSViewControllerPresentationMethodPush;
[self.navigationController pushViewController:vc animated:YES];

以模拟方式呈现导航:

DETestViewController *vc = [DETestViewController new];
vc.viewControllerPresentationMethod = SSViewControllerPresentationMethodModal;
UINavigationController *nav = [[UINavigationController alloc]
                               initWithRootViewController:vc];
[self presentViewController:nav animated:YES completion:nil];

以模态呈现:

DETestViewController *vc = [DETestViewController new];
vc.viewControllerPresentationMethod = SSViewControllerPresentationMethodModal;
[self presentViewController:vc animated:YES completion:nil];

另外,在DEViewController中,我们可以添加一个回退到&#34;检查&#34; 如果上述财产等于SSViewControllerPresentationMethodUnspecified

- (BOOL)isViewControllerPushed
{
    if (self.viewControllerPresentationMethod != SSViewControllerPresentationMethodUnspecified) {
        return (BOOL)(self.viewControllerPresentationMethod == SSViewControllerPresentationMethodPush);
    }

    else {
        // fallback to default determination method
        return (BOOL)self.navigationController.viewControllers.count > 1;
    }
}
Yevhen Dubinin answered 2019-08-18T18:29:52Z
3 votes

假设您以模态方式呈现的所有viewControllers都包含在一个新的navigationController中(您应该始终这样做),您可以将此属性添加到VC中。

private var wasPushed: Bool {
    guard let vc = navigationController?.viewControllers.first where vc == self else {
        return true
    }

    return false
}
Demosthese answered 2019-08-18T18:30:19Z
2 votes

self.navigationController != nil意味着它在导航堆栈中。

Daniel answered 2019-08-18T18:30:45Z
1 votes

要检测您的控制器是否被推或只是在您想要的任何地方使用下面的代码:

if ([[[self.parentViewController childViewControllers] firstObject] isKindOfClass:[self class]]) {

    // Not pushed
}
else {

    // Pushed
}

我希望这段代码可以帮助任何人......

Arash Zeinoddini answered 2019-08-18T18:31:18Z
0 votes

如果您使用的是ios 5.0或更高版本,请使用此代码

-(BOOL)isPresented
{
if ([self isBeingPresented]) {
    // being presented
     return YES;
} else if ([self isMovingToParentViewController]) {
    // being pushed
     return NO;
} else {
    // simply showing again because another VC was dismissed
     return NO;
}

}

Shahbaz Abbasi answered 2019-08-18T18:31:46Z
0 votes
if let navigationController = self.navigationController, navigationController.isBeingPresented {
    // being presented
}else{
    // being pushed
}
mkto answered 2019-08-18T18:32:07Z
-1 votes
id presentedController = self.navigationController.modalViewController;
if (presentedController) {
     // Some view is Presented
} else {
     // Some view is Pushed
}

这将告诉您是否呈现或推送了viewController

iCoder86 answered 2019-08-18T18:32:34Z
-1 votes

对于一些想知道的人,如何告诉ViewController它正在呈现

如果override func viewDidLoad() { super.viewDidLoad() if self.vcPresentationStyle == .Present { //is being presented } else { //is being pushed } } 正在展示/推送B

  1. presentationStyle中定义override func viewDidLoad() { super.viewDidLoad() if self.vcPresentationStyle == .Present { //is being presented } else { //is being pushed } } B

    override func viewDidLoad() {
        super.viewDidLoad()
    
        if self.vcPresentationStyle == .Present {
            //is being presented 
        }
        else {
            //is being pushed
        }
    
    }
    
  2. 现在在override func viewDidLoad() { super.viewDidLoad() if self.vcPresentationStyle == .Present { //is being presented } else { //is being pushed } } 视图控制器中,通过分配presentationStyle告诉B它是否正在显示/推送

    override func viewDidLoad() {
        super.viewDidLoad()
    
        if self.vcPresentationStyle == .Present {
            //is being presented 
        }
        else {
            //is being pushed
        }
    
    }
    
  3. 用法override func viewDidLoad() { super.viewDidLoad() if self.vcPresentationStyle == .Present { //is being presented } else { //is being pushed } } View Controller

    override func viewDidLoad() {
        super.viewDidLoad()
    
        if self.vcPresentationStyle == .Present {
            //is being presented 
        }
        else {
            //is being pushed
        }
    
    }
    
Saif answered 2019-08-18T18:33:41Z
translate from https://stackoverflow.com:/questions/23620276/check-if-view-controller-is-presented-modally-or-pushed-on-a-navigation-stack