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

Как определить, что представлен UIViewController

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

Во всех доступных версиях, например, 4.3, 5.0, до 6.0, из подкласса UIViewController, могу ли я предположить, что контроллер вида представлен (modally), если выполняется следующее условие.

if(self.parentViewController == nil || self.navigationController == nil)
4b9b3361

Ответ 1

С iOS 5 UIViewController получил свойство readonly с именем presentingViewController, которое заменяет старую семантику parentViewController (которая теперь описывает сдерживание). Это свойство может использоваться, когда диспетчеру просмотра необходимо получить доступ к контроллеру представления, который его представляет - заметьте: это часто будет чем-то другим, чем ожидалось бы, если вы новичок в API!

Кроме того, свойство isBeingPresented было введено, чтобы в значительной степени решить класс ситуаций, в которые вы сейчас находитесь. Проверьте это свойство в своих контроллерах вида viewWillAppear:.

Update

Я перепробовал, что вы, похоже, тоже нацелены на iOS 4.3:
В этом случае вам нужно защитить вызов isBeingPresented с помощью if ([self respondsToSelector:…]), который вы можете в блоке else проверить, не является ли parentViewController не нулем.

Другим подходом к обратной совместимости может быть переопределение +resolveInstanceMethod: для добавления реализации для -isBeingPresented во время выполнения. Это приведет к тому, что ваши вызывающие сайты будут чистыми, и вы избавитесь от магии времени выполнения, как только вы отпустите поддержку iOS iOS. -)

Заметим, однако, что к этому относятся случаи краев, и вы также начинаете свой подход, когда работаете на iOS < 5:

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

Ответ 2

Я использую этот код, чтобы проверить, представлен ли UIViewController.

if (uiviewcontroller.presentingViewController != nil) {
   // do something
}

Ответ 3

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

BOOL presented = [[self.navigationController viewControllers] count] == 1;

Ответ 4

Чтобы справиться с таким поведением, я обычно устанавливаю / reset BOOL, переключая его в viewWillAppear/viewWillDisappear.

Кстати, ваше тестовое состояние кажется неправильным. Я думаю, вы должны использовать

if(self.parentViewController != nil || self.navigationController != nil)

Почему вы не можете просто добавить панель инструментов в свой контроллер? Есть ли случай, когда представление загружено, но не представлено?

Ответ 5

@saikamesh.

Поскольку вы используете UINavigationController для навигации по вашим диспетчеру просмотра, я думаю, вы можете использовать topViewController (Doc здесь) и visibleViewController (Doc снова), чтобы достичь ваших целей.

Вы упомянули, что:

когда он помещается в стек навигации, тогда кнопка закрытия по умолчанию будет добавлен, если пользователь сможет вернуться назад

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

id specificVC = [SpecificViewController sharedInstance];
if (specificVC.isPushed) {
    [self.navController popToViewController:specificVC animated:YES];
}

и проверить, представлен ли он:

if ([self.navController.visibleViewController isKindOfClass:[SpecificViewController class]]) {
    // Hide or add close button
    self.isPresented = YES;
}

Или вы можете прочитать принятый ответ.

:) Надежда помогает.

Ответ 6

Пожалуйста, проверьте этот способ:

 for (UIViewController*vc in [self.navigationController viewControllers]) {
    if ([vc isKindOfClass: [OffersViewController class]]){ //this line also checks OffersViewController is presented or not 

        if(vc.isViewLoaded){
             NSLog(@"Yes");
        }

    }
}

Ответ 7

Вы можете сделать это так, быстро и безопасно

UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;

// Find the top controller on the view hierarchy
while (topController.presentedViewController) {
    topController = topController.presentedViewController;
}

// If the top controller it is not already presented
if (![topController isKindOfClass:[YourViewController class]]) {
    // Present it
    [topController presentViewController:yourViewController animated:YES completion:nil];
}
else {
// do some stuff here
}

Ответ 8

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

   UIViewController *presentedController = self.navigationController.modalViewController;
   if (presentedController) {
      // At this point, you have a view controller presented from your navigation controller
      if ([presentedController isKindOfClass:[controllerYouWantToCheck class]]) {
         // add your toolbar/buttons/etc here
      }
   }

Ответ 9

Один из элегантных ответов, которые я не видел здесь:

// Edit: Added 2 other modal cases
extension UIViewController {
    var isModal: Bool { 
        return self.presentingViewController?.presentedViewController == self
            || (navigationController != nil && navigationController?.presentingViewController?.presentedViewController == navigationController)
            || tabBarController?.presentingViewController is UITabBarController
    }
}

кредит: на основе этот смысл

Ответ 10

В Swift на iOS 9 (или позже):

if viewController.viewIfLoaded?.window != nil {
    // viewController is visible
}

Ответ 11

Если бы это был я, у меня был бы специальный метод init и его использование при создании vc.

vc = [[[MyUIViewControllerSubClass alloc] init] initWithToolbarAndCloseButton:YES];

Ответ 12

Небольшая модификация в ответе @AmitaiB для создания функции,

func isModallyPresented(tmpVC:UIViewController) -> Bool {
        return tmpVC.presentingViewController?.presentedViewController == tmpVC
            || (tmpVC.navigationController != nil && tmpVC.navigationController?.presentingViewController?.presentedViewController == tmpVC.navigationController)
            || tmpVC.tabBarController?.presentingViewController is UITabBarController
    }

Просто проверьте по телефону:

if(isModallyPresented(tmpVC:myTopVC)){
//return true if viewcontroller is presented 
}

Ответ 13

Как сказал Мартин Рид, это лучший способ

            BOOL presented = [[self.navigationController viewControllers] count] == 1;
        if (presented) {
            [self dismissViewControllerAnimated:YES completion:^{
                // do whatever you need here
            }];
        }
        else {
            [self.navigationController popViewControllerAnimated:YES];
        }