it-swarm.com.ru

Проверьте, представлен ли контроллер представления модально или помещен в стек навигации

Как я могу, в моем коде контроллера представления, различать:

  • представлен модально
  • толкнул на стек навигации

И presentingViewController, и isMovingToParentViewController являются 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];

Думаю, мне лучше сообщить контролеру вида, когда он модальный, вместо того, чтобы пытаться определить.

91
meaning-matters

Бери с крошкой соли, не тестировал.

- (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;
 }
113
ColdLogic

Вы пропустили один метод: 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
    }
}
65
rmaddy

В Свифт :

// 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 || false
    }
}
57
King-Wizard

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
   }
}
18
Jibeex

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
        }
    }
}

До сих пор это работает для меня . Если некоторые оптимизации, пожалуйста, поделитесь.

17
Jonauz

Swift 4

var isModal: Bool {
    return presentingViewController != nil ||
           navigationController?.presentingViewController?.presentedViewController === navigationController ||
           tabBarController?.presentingViewController is UITabBarController
}
12
Charlton Provatas

Как многие здесь предполагают, что методы «проверки» не работают хорошо для всех случаев, в моем проекте я нашел решение для управления этим вручную…. Дело в том, что мы обычно управляем презентацией самостоятельно - это не то, что происходит за сценой, и мы должны проанализировать.

DEViewController.h файл:

#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;
    }
}
3
Yevhen Dubinin

Предполагая, что все viewController, которые вы представляете модально, обернуты внутри нового navigationController (что вы всегда должны делать), вы можете добавить это свойство в свой VC.

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

    return false
}
3
Demosthese

self.navigationController != nil будет означать, что он находится в стеке навигации.

2
Daniel

Чтобы обнаружить, что ваш контроллер выдвинут или нет, просто используйте приведенный ниже код в любом месте:

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

    // Not pushed
}
else {

    // Pushed
}

Я надеюсь, что этот код может помочь любому ...

1
Arash Zeinoddini

Если вы используете 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;
}

}

0
Shahbaz Abbasi
if let navigationController = self.navigationController, navigationController.isBeingPresented {
    // being presented
}else{
    // being pushed
}
0
mkto