Проверьте, представлен ли контроллер вида модально или помещен в стек навигации
как я могу, в моем коде контроллера зрения, различать:
- представлен модально
- нажал на навигационный стек
и presentingViewController
и isMovingToParentViewController
are 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 ответов:
возьмите с крупинкой соли, не тестировали.
- (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; }
вы упустили один метод:
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 } }
In Свифт:
func isModal() -> Bool { if self.presentingViewController != nil { return true } else if self.navigationController?.presentingViewController?.presentedViewController == self.navigationController { return true } else if self.tabBarController?.presentingViewController is UITabBarController { return true } return false }
self.navigationController != ноль будет означать, что это в навигации стек.
чтобы обработать случай, когда текущий контроллер вида нажимается, пока навигационный контроллер представлен модально, я добавил несколько строк кода, чтобы проверить, является ли текущий контроллер вида корневым контроллером в стеке навигации .
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 } }
Swift 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 } } }
это работает для меня до сих пор. Если некоторые оптимизации, пожалуйста, поделитесь.
Swift 4
var isModal: Bool { return presentingViewController != nil || navigationController?.presentingViewController?.presentedViewController === navigationController || tabBarController?.presentingViewController is UITabBarController }
как многие люди здесь предполагают, что методы" проверки " не работают хорошо для всех случаев, в моем проекте я придумал решение для управления этим вручную. Дело в том, что мы обычно управляем презентацией самостоятельно - это не то, что происходит за сценой, и мы должны интроспектировать.
DEViewController.h
file:#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
мы могли бы добавить запасной вариант для "проверки", если вышеупомянутое свойство равно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; } }
предполагая, что все viewControllers, которые вы представляете модально, обернуты внутри нового navigationController (что вы всегда должны делать в любом случае), вы можете добавить это свойство в свой VC.
private var wasPushed: Bool { guard let vc = navigationController?.viewControllers.first where vc == self else { return true } return false }
чтобы обнаружить ваш контроллер нажимается или не просто использовать ниже код в любом месте вы хотите:
if ([[[self.parentViewController childViewControllers] firstObject] isKindOfClass:[self class]]) { // Not pushed } else { // Pushed }
Я надеюсь, что этот код может помочь любому...
Если вы используете 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; }
}
if let navigationController = self.navigationController, navigationController.isBeingPresented { // being presented }else{ // being pushed }
id presentedController = self.navigationController.modalViewController; if (presentedController) { // Some view is Presented } else { // Some view is Pushed }
Это даст вам знать, если viewController представлен или нажат
для тех, кто задается вопросом, Как сказать ViewController, что он представлен
если
A
представляет/толканияB
определение
enum
иproperty
наB
enum ViewPresentationStyle { case Push case Present } //and write property var vcPresentationStyle : ViewPresentationStyle = .Push //default value, considering that B is pushed
сейчас
A
контроллер посмотреть, сказатьB
если он представляется / толкнул, назначивpresentationStyle
func presentBViewController() { let bViewController = B() bViewController.vcPresentationStyle = .Present //telling B that it is being presented self.presentViewController(bViewController, animated: true, completion: nil) }
использование
B
посмотреть Контроллерoverride func viewDidLoad() { super.viewDidLoad() if self.vcPresentationStyle == .Present { //is being presented } else { //is being pushed } }