Как определить предыдущий контроллер вида в стеке навигации
у меня есть 2 отдельные navigationcontrollers, с RootViewController A и другой с RootViewController B.
Я могу нажать ViewController C в навигационный стек A или B.
вопрос: когда я в ViewController C, как я могу узнать, если я нахожусь в стеке, принадлежащем A или B?
17 ответов:
можно использовать
UINavigationController' sviewControllersсвойства:
@property(nonatomic, copy) NSArray *viewControllersОбсуждение: корневой контроллер вида находится в индексе 0 в массиве, контроллер заднего вида находится в индексе n-2, а верхний контроллер находится в индексе n-1, где n-количество элементов в массиве.
https://developer.apple.com/documentation/uikit/uinavigationcontroller
вы можете использовать это, чтобы проверить, является ли корневой вид контроллер (один в индексе массива 0) - это контроллер вида A или B.
вот реализация принятого ответа:
- (UIViewController *)backViewController { NSInteger numberOfViewControllers = self.navigationController.viewControllers.count; if (numberOfViewControllers < 2) return nil; else return [self.navigationController.viewControllers objectAtIndex:numberOfViewControllers - 2]; }
- (UIViewController *)backViewController { NSInteger myIndex = [self.navigationController.viewControllers indexOfObject:self]; if ( myIndex != 0 && myIndex != NSNotFound ) { return [self.navigationController.viewControllers objectAtIndex:myIndex-1]; } else { return nil; } }
более общая реализация принятого ответа:
- (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; }это вернет правильный "контроллер заднего вида" независимо от того, где текущий класс находится в стеке навигации.
быстрая реализация 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 } }
вот модифицированная версия Прабху Бимана 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 } }
доступ в интернет
n-2элементviewControllersсвойство для доступа к главному контроллеру представления.как только у вас есть этот экземпляр, вы можете проверить его тип, регистрируя то, что выходит из
NSStringFromClass()
быстрая реализация кода @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 }
использовать
navigationControllerметод для его получения. Смотрите документация на сайте Apple.navigationController родитель или предок, который является навигационной контроллер. (только для чтения)
@property (nonatomic, readonly, retain) UINavigationController *navigationController
Обсуждение возвращает только навигационный контроллер, если вид контроллер в стек. Это свойство равно нулю, если a навигация контроллер не может быть найден.
в наличии доступно в iOS 2.0 и более поздних версиях.
потому что мертвые лошади любят быть избитыми:)
- (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]; }
найти предыдущий контроллер вида просто.
в вашем случае, т. е. вы находитесь в C, и вам нужно B,
[self.navigationController.viewControllers lastObject]Это то, что вы хотите.для A, так как A является контроллером корневого представления, вы можете просто заменить
lastObjectСfirstObjectполучить.
С помощью Swift с помощью guard.
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] } }
мое расширение, swift 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 } } }
для swift 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, который вы хотите вернуть.
более емкие Свифт impementation:
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] } }
Comments