Как определить предыдущий контроллер представления в стеке навигации
У меня есть 2 отдельно navigationcontrollers
, один с RootViewController
A, а другой с RootViewController
B.
Я могу нажать ViewController
C на любой стек навигации A или B.
Вопрос: Когда я нахожусь в ViewController
C, как я могу узнать, есть ли я в стеке, принадлежащем A или B?
Ответы
Ответ 1
Вы можете использовать свойство UINavigationController
viewControllers
:
@property(nonatomic, copy) NSArray *viewControllers
Обсуждение. Контроллер корневого представления имеет индекс 0 в массиве, контроллер заднего вида - индекс n-2, а верхний контроллер - в индексе n-1, где n - количество элементов в массиве.
https://developer.apple.com/documentation/uikit/uinavigationcontroller
Вы можете использовать это для проверки того, является ли контроллер корневого представления (тот, что у индекса массива 0), контроллером просмотра A или B.
Ответ 2
Здесь реализация принятого ответа:
- (UIViewController *)backViewController
{
NSInteger numberOfViewControllers = self.navigationController.viewControllers.count;
if (numberOfViewControllers < 2)
return nil;
else
return [self.navigationController.viewControllers objectAtIndex:numberOfViewControllers - 2];
}
Ответ 3
- (UIViewController *)backViewController
{
NSInteger myIndex = [self.navigationController.viewControllers indexOfObject:self];
if ( myIndex != 0 && myIndex != NSNotFound ) {
return [self.navigationController.viewControllers objectAtIndex:myIndex-1];
} else {
return nil;
}
}
Ответ 4
Более общая реализация принятого ответа:
- (UIViewController *)backViewController {
NSArray * stack = self.navigationController.viewControllers;
for (int i=stack.count-1; i > 0; --i)
if (stack[i] == self)
return stack[i-1];
return nil;
}
Это вернет правильный "контроллер заднего вида" независимо от того, где текущий класс находится в стеке навигации.
Ответ 5
Быстрая реализация tjklemz в качестве расширения:
extension UIViewController {
func backViewController() -> UIViewController? {
if let stack = self.navigationController?.viewControllers {
for(var i=stack.count-1;i>0;--i) {
if(stack[i] == self) {
return stack[i-1]
}
}
}
return nil
}
}
Ответ 6
Здесь измененная версия кода Prabhu Beeman's Swift, которая адаптирует его для поддержки Swift 3:
extension UIViewController {
func backViewController() -> UIViewController? {
if let stack = self.navigationController?.viewControllers {
for i in (1..<stack.count).reverse() {
if(stack[i] == self) {
return stack[i-1]
}
}
}
return nil
}
}
Ответ 7
Доступ к элементу n-2
свойства viewControllers
для доступа к контроллеру родительского представления.
После того, как у вас есть этот экземпляр, вы можете проверить его тип, зарегистрировав то, что вышло из NSStringFromClass()
. Или вы можете сохранить строку идентификатора static const
в контроллерах A и B и функцию getter, которая выводит строку.
Ответ 8
Быстрая реализация кода @tjklemz:
var backViewController : UIViewController? {
var stack = self.navigationController!.viewControllers as Array
for (var i = stack.count-1 ; i > 0; --i) {
if (stack[i] as UIViewController == self) {
return stack[i-1] as? UIViewController
}
}
return nil
}
Ответ 9
Как расширение UINavigationController
:
extension UINavigationController {
func previousViewController() -> UIViewController? {
guard viewControllers.count > 1 else {
return nil
}
return viewControllers[viewControllers.count - 2]
}
}
Ответ 10
Используйте метод navigationController
для его извлечения. Смотрите документацию на сайте Apple.
navigationController Родитель или предок, являющийся навигацией контроллер. (Только для чтения)
@property (nonatomic, readonly, сохранить) UINavigationController * NavigationController
Обсуждение Только возвращает контроллер навигации, если вид контроллер находится в стеке. Это свойство равно нулю, если навигация контроллер не может быть найден.
Доступность Доступна в iOS 2.0 и более поздних версиях.
Ответ 11
Потому что мертвые лошади любят быть избитыми:)
- (UIViewController *)previousViewController
{
NSArray *vcStack = self.navigationController.viewControllers;
NSInteger selfIdx = [vcStack indexOfObject:self];
if (vcStack.count < 2 || selfIdx == NSNotFound) { return nil; }
return (UIViewController *)[vcStack objectAtIndex:selfIdx - 1];
}
Ответ 12
Найти предыдущий контроллер представления прост.
В вашем случае, т.е. вы находитесь на C, и вам нужно B, [self.navigationController.viewControllers lastObject]
- это то, что вы хотите.
Для A, поскольку A является контроллером корневого представления, вы можете просто заменить lastObject
на firstObject
, чтобы получить.
Ответ 13
Реализация для Swift 2.2 - добавьте это в расширение UIViewController
. Безопасный в том смысле, что он вернет nil
, если viewcontroller является rootvc или нет в диспетчере навигации.
var previousViewController: UIViewController? {
guard let viewControllers = navigationController?.viewControllers else {
return nil
}
var previous: UIViewController?
for vc in viewControllers{
if vc == self {
break
}
previous = vc
}
return previous
}
Ответ 14
С помощью Swift с защитой.
extension UIViewController {
func getPreviousViewController() -> UIViewController? {
guard let _ = self.navigationController else {
return nil
}
guard let viewControllers = self.navigationController?.viewControllers else {
return nil
}
guard viewControllers.count >= 2 else {
return nil
}
return viewControllers[viewControllers.count - 2]
}
}
Ответ 15
Мое расширение, быстрое 3
extension UIViewController {
var previousViewController: UIViewController? {
guard let controllers = navigationController?.viewControllers, controllers.count > 1 else { return nil }
switch controllers.count {
case 2: return controllers.first
default: return controllers.dropLast(2).first
}
}
}
Ответ 16
для быстрого 3 вы можете сделать это:
var backtoViewController:UIViewController!
for viewController in (self.navigationController?.viewControllers)!.reversed() {
if viewController is NameOfMyDestinationViewController {
backtoViewController = viewController
}
}
self.navigationController!.popToViewController(backtoViewController, animated: true)
Вам нужно только заменить "NameOfMyDestinationViewController" на viewController, который вы хотите вернуть.
Ответ 17
Более кратковременная имплантация:
extension UIViewController {
var previousViewController: UIViewController? {
guard let nav = self.navigationController,
let myIdx = nav.viewControllers.index(of: self) else {
return nil
}
return myIdx == 0 ? nil : nav.viewControllers[myIdx-1]
}
}