Проверьте, представлен ли диспетчер представлений модельным способом или нажат на стек навигации
Как я могу, по моему мнению, определить код контроллера:
- представлен модально
- нажата на стек навигации
Оба 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];
Думаю, мне лучше сказать, что мой контроллер просмотра, когда он модальный, вместо того, чтобы пытаться определить.
Ответы
Ответ 1
Возьмите с солью, не испытайте.
- (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;
}
Ответ 2
В 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
}
}
Ответ 3
Вы упускаете из виду один метод: 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
}
}
Ответ 4
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
}
}
Ответ 5
Swift 5
Вот решение, которое решает проблему, упомянутую в предыдущих ответах, когда isModal()
возвращает true
, если нажатый UIViewController
находится в представленном стеке UINavigationController
.
extension UIViewController {
var isModal: Bool {
if let index = navigationController?.viewControllers.firstIndex(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
}
}
}
До сих пор это работает для меня.
Если какие-то оптимизации, пожалуйста, поделитесь.
Ответ 6
Swift 4
var isModal: Bool {
return presentingViewController != nil ||
navigationController?.presentingViewController?.presentedViewController === navigationController ||
tabBarController?.presentingViewController is UITabBarController
}
Ответ 7
Как многие люди здесь предлагают, что методы "проверки" не работают хорошо для всех случаев, в моем проекте я придумал решение для управления этим вручную.
Дело в том, что мы обычно управляем презентацией самостоятельно - это не то, что происходит за сценой, и мы должны задуматься.
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;
}
}
Ответ 8
Предполагая, что все viewControllers, которые вы представляете модально, обернуты внутри нового navigationController (который вы всегда должны делать в любом случае), вы можете добавить это свойство в свой VC.
private var wasPushed: Bool {
guard let vc = navigationController?.viewControllers.first where vc == self else {
return true
}
return false
}
Ответ 9
self.navigationController != nil
будет означать его в стеке навигации.
Ответ 10
Чтобы обнаружить, что ваш контроллер выдвинут или нет, просто используйте приведенный ниже код в любом месте:
if ([[[self.parentViewController childViewControllers] firstObject] isKindOfClass:[self class]]) {
// Not pushed
}
else {
// Pushed
}
Я надеюсь, что этот код может помочь любому...
Ответ 11
if let navigationController = self.navigationController, navigationController.isBeingPresented {
// being presented
}else{
// being pushed
}
Ответ 12
Если вы используете 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;
}
}
Ответ 13
if navigationController.presentingViewController != nil {
// Navigation controller is being presented modally
}
Ответ 14
id presentedController = self.navigationController.modalViewController;
if (presentedController) {
// Some view is Presented
} else {
// Some view is Pushed
}
Это даст вам знать, представлен ли viewController или нажат
Ответ 15
Для кого-то, кто задается вопросом, Как сообщить 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
View Controller
override func viewDidLoad() {
super.viewDidLoad()
if self.vcPresentationStyle == .Present {
//is being presented
}
else {
//is being pushed
}
}