Подтвердить что ты не робот

Можно ли определить, представлен ли ViewController как модальный?

Можно ли проверить внутри класса ViewController, что он представлен в виде модального контроллера?

4b9b3361

Ответ 1

Так как modalViewController устарел в iOS 6, вот версия, которая работает для iOS 5+ и компилируется без предупреждений.

Objective-C:

- (BOOL)isModal {
    return self.presentingViewController.presentedViewController == self
      || (self.navigationController != nil && self.navigationController.presentingViewController.presentedViewController == self.navigationController)
      || [self.tabBarController.presentingViewController isKindOfClass:[UITabBarController class]];
}

Swift:

var isModal: Bool {
    return self.presentingViewController?.presentedViewController == self
        || (self.navigationController != nil && self.navigationController?.presentingViewController?.presentedViewController == self.navigationController)
        || self.tabBarController?.presentingViewController is UITabBarController
}

Совет шляпы к ответу Фелипе.

Ответ 2

Если вы ищете iOS 6+, этот ответ устарел, и вы должны проверить ответ Gabriele Petronella


Нет никакого опрятного способа сделать это, как свойство или метод, родные для UIKit. Что вы можете сделать, это проверить несколько аспектов вашего контроллера, чтобы убедиться, что он представлен как модальный.

Итак, чтобы проверить, представлен ли текущий (представленный как self в коде ниже), контроллер представлен модально или нет, у меня есть функция ниже или в категории UIViewController, или (если вашему проекту не нужно использовать другие контроллеры UIKit, например, UITableViewController) в базовом контроллере, который мои другие контроллеры наследуют

-(BOOL)isModal {

     BOOL isModal = ((self.parentViewController && self.parentViewController.modalViewController == self) || 
            //or if I have a navigation controller, check if its parent modal view controller is self navigation controller
            ( self.navigationController && self.navigationController.parentViewController && self.navigationController.parentViewController.modalViewController == self.navigationController) || 
            //or if the parent of my UITabBarController is also a UITabBarController class, then there is no way to do that, except by using a modal presentation
            [[[self tabBarController] parentViewController] isKindOfClass:[UITabBarController class]]);

    //iOS 5+
    if (!isModal && [self respondsToSelector:@selector(presentingViewController)]) {

        isModal = ((self.presentingViewController && self.presentingViewController.modalViewController == self) || 
             //or if I have a navigation controller, check if its parent modal view controller is self navigation controller
             (self.navigationController && self.navigationController.presentingViewController && self.navigationController.presentingViewController.modalViewController == self.navigationController) || 
             //or if the parent of my UITabBarController is also a UITabBarController class, then there is no way to do that, except by using a modal presentation
             [[[self tabBarController] presentingViewController] isKindOfClass:[UITabBarController class]]);

    }

    return isModal;        

}

EDIT: Я добавил последнюю проверку, чтобы проверить, используется ли UITabBarController, и вы представляете другой UITabBarController как модальный.

EDIT 2: добавлена ​​проверка iOS 5+, где UIViewController больше не отвечает за parentViewController, а вместо presentingViewController.

РЕДАКТИРОВАТЬ 3: я создал для него смысл на всякий случай https://gist.github.com/3174081

Ответ 3

В iOS5 +, как вы можете видеть в Справочник класса UIViewController, вы можете получить его из свойства "presentingViewController".

presentingViewController Контроллер представления, который представил этот контроллер. (Только для чтения)

@property (nonatomic, readonly) UIViewController * presentingViewController
Обсуждение

Если контроллер вида, который получил это сообщение, представлен другим контроллером представления, это свойство содержит контроллер представления, который его представляет. Если контроллер представления не представлен, но представлен один из его предков, это свойство содержит контроллер представления, представляющий ближайшего предка. Если ни контроллер представления, ни его предки не представлены, это свойство имеет значение nil.

Доступность
Доступно в iOS 5.0 и более поздних версиях.
Объявлено в
UIViewController.h

Ответ 4

Если этого не существует, вы можете определить свойство для этого (presentedAsModal) в вашем подклассе UIViewController и установить его в YES перед представлением ViewController в качестве модального представления.

childVC.presentedAsModal = YES;
[parentVC presentModalViewController:childVC animated:YES];

Вы можете проверить это значение в своем переопределении viewWillAppear.

Я считаю, что нет официального свойства, которое указывает, как представление представлено, но ничто не мешает вам создавать свои собственные.

Ответ 5

Ответ Petronella не работает, если self.navigationController модально представлен, но сам не равен self.navigationController.viewControllers [0], в этом случае self push,

Вот как вы могли бы исправить эту проблему.

return self.presentingViewController.presentedViewController == self
            || (self.navigationController != nil && self.navigationController.presentingViewController.presentedViewController == self.navigationController && self == self.navigationController.viewControllers[0])
            || [self.tabBarController.presentingViewController isKindOfClass:[UITabBarController class]];

И в Swift:

return self.presentingViewController?.presentedViewController == self
        || (self.navigationController != nil && self.navigationController?.presentingViewController?.presentedViewController == self.navigationController && self.navigationController?.viewControllers[0] == self)
        || self.tabBarController?.presentingViewController is UITabBarController

Ответ 6

Это должно сработать.

if(self.parentViewController.modalViewController == self)…

Ответ 7

Лучший способ проверить

 if (self.navigationController.presentingViewController) {
         NSLog(@"Model Present");
    }

Ответ 8

Если вам не нужно различать полноэкранные модальные представления и немодальные представления, что имеет место в моем проекте (я имел дело с проблемой, которая возникает только с листами форм и страницами страниц), вы можете используйте свойство modalPresentationStyle UIViewController:

switch (self.modalPresentationStyle) {
    case 0: NSLog(@"full screen, or not modal"); break;
    case 1: NSLog(@"page sheet"); break;
    case 2: NSLog(@"form sheet"); break;
}

Ответ 9

В Swift:

func isUIViewControllerPresentedAsModal() -> Bool {
    if((self.presentingViewController) != nil) {
        return true
    }

    if(self.presentingViewController?.presentedViewController == self) {
        return true
    }

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

    if((self.tabBarController?.presentingViewController?.isKindOfClass(UITabBarController)) != nil) {
        return true
    }

    return false
}

Ответ 10

В моем проекте у меня есть контроллер представления (Detail), который может быть представлен как модально (при добавлении нового элемента), так и с помощью push (при редактировании существующего) с помощью контроллера главного представления. Когда пользователь отбирает [Done], контроллер подробного представления вызывает метод контроллера Master view, чтобы сообщить, что он готов к закрытию. Мастер должен определить, как подробно представлена ​​деталь, чтобы узнать, как ее закрыть. Вот как я это делаю:

UIViewController *vc = self.navigationController.viewControllers.lastObject;
if (vc == self) {
    [self dismissViewControllerAnimated:YES completion:NULL];
} else {
    [self.navigationController popViewControllerAnimated:YES];
}

Ответ 11

Такой способ может работать.

UIViewController* child = self;
UIViewController* parent = child.parentViewController;
while (parent && parent.modalViewController != child) {
    child = parent;
    parent = child.parentViewController;
}
if (parent) {
    // A view controller in the hierarchy was presented as a modal view controller
}

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

Ответ 12

Что для меня работало:

// this is the trick: set parent view controller as application window root view controller
UIApplication.sharedApplication.delegate.window.rootViewController = viewController;

// assert no modal view is presented
XCTAssertNil(viewController.presentedViewController);

// simulate button tap which shows modal view controller
[viewController.deleteButton sendActionsForControlEvents:UIControlEventTouchUpInside];

// assert that modal view controller is presented
XCTAssertEqualObjects(viewController.presentedViewController.class, MyModalViewController.class);

Насколько я тестировал, это работает для iOS7 и iOS8. Однако не пытайтесь использовать iOS6.

Ответ 13

Я немного подошел, чтобы найти правильный ответ на этот вопрос, и я не мог найти ни одного, который охватывал бы все возможные сценарии. Я написал эти несколько строк кода, которые, похоже, выполняют эту работу. Вы можете найти несколько встроенных комментариев, чтобы выяснить, что было проверено.

- (BOOL)isModal {
    BOOL modal = NO;
    if ([self presentingViewController]) { //Some view Controller is presenting the current stack
        UIViewController *presented = [[self presentingViewController] presentedViewController]; // What been presented
        if ([presented respondsToSelector:@selector(viewControllers)]) { // There a stack
            NSArray *viewControllers = [presented performSelector:@selector(viewControllers)];
            modal = [viewControllers firstObject] == self; // Current VC is presented modally if it the first in the stack
        }
        else {
            modal = presented == self; // Don't think this is actually needed. set modal = YES should do the job tho.
        }
    }
    return modal;
}

Надеюсь на эту помощь.

Ответ 14

Здесь моя измененная версия @GabrielePetronella isModal, которая работает с содержащимися контроллерами представлений, поскольку она сначала подбирает иерархию parentViewController. Также вытащил код на несколько строк, чтобы он понял, что он делает.

var isModal: Bool {
    // If we are a child view controller, we need to check our parent presentation
    // rather than our own.  So walk up the chain until we don't see any parentViewControllers
    var potentiallyPresentedViewController : UIViewController = self
    while (potentiallyPresentedViewController.parentViewController != nil) {
        potentiallyPresentedViewController = potentiallyPresentedViewController.parentViewController!
    }

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

    if let navigationController = potentiallyPresentedViewController.navigationController {
        if navigationController.presentingViewController?.presentedViewController == navigationController {
            return true
        }
    }

    return potentiallyPresentedViewController.tabBarController?.presentingViewController is UITabBarController
}