Итак, я нажимаю контроллер представления из RootViewController, например:
[self.navigationController pushViewController:anotherViewController animated:YES] ;
НО, FROM anotherViewController
теперь, я хочу снова получить доступ к RootViewController.
Я пытаюсь
// (inside anotherViewController now)
///RootViewController *root = (RootViewController*)self.parentViewController ; // No.
// err
RootViewController *root = (RootViewController*)[self.navigationController.viewControllers objectAtIndex:0] ; // YES!! it works
Я не уверен, ПОЧЕМУ это работает, и я не уверен, что это лучший способ сделать это. Может кто-нибудь прокомментировать лучший способ получить RootViewController от контроллера, который вы ввели в этот контроллер навигации RootViewController, и независимо от того, насколько я это сделал, надежен или нет?
Ответ 1
Используйте свойство viewControllers свойства UINavigationController. Пример кода:
// Inside another ViewController
NSArray *viewControllers = self.navigationController.viewControllers;
UIViewController *rootViewController = [viewControllers objectAtIndex:viewControllers.count - 2];
Это стандартный способ получения "обратного" контроллера вида. Причина objectAtIndex:0
заключается в том, что контроллер просмотра, к которому вы пытаетесь получить доступ, также является корневым, если вы были глубже в навигации, вид назад не был бы таким же, как корневой вид.
Ответ 2
Быстрая версия:
var rootViewController = self.navigationController?.viewControllers.first
Версия ObjectiveC:
UIViewController *rootViewController = [self.navigationController.viewControllers firstObject];
Где self - это экземпляр UIViewController, встроенный в UINavigationController.
Ответ 3
Немного менее уродливая версия того же самого, упомянутого в почти всех этих ответах:
UIViewController *rootViewController = [[self.navigationController viewControllers] firstObject];
в вашем случае, я бы, наверное, сделал что-то вроде:
внутри вашего подкласса UINavigationController:
- (UIViewController *)rootViewController
{
return [[self viewControllers] firstObject];
}
то вы можете использовать:
UIViewController *rootViewController = [self.navigationController rootViewController];
изменить
OP запросил свойство в комментариях.
если вы хотите, вы можете получить к нему доступ через что-то вроде self.navigationController.rootViewController
, просто добавив свойство readonly в свой заголовок:
@property (nonatomic, readonly, weak) UIViewController *rootViewController;
Ответ 4
Для всех, кто заинтересован в быстром расширении, это то, что я сейчас использую:
extension UINavigationController {
var rootViewController : UIViewController? {
return self.viewControllers.first as? UIViewController
}
}
Ответ 5
В дополнение к ответу @dulgan, это всегда хороший подход - использовать firstObject
objectAtIndex:0
, потому что, в то время как первый возвращает nil, если в массиве нет объекта, последний выдает исключение.
UIViewController *rootViewController = self.navigationController.rootViewController;
В качестве альтернативы было бы большим плюсом для вас создать категорию с именем UINavigationController+Additions
и определить в ней свой метод.
@interface UINavigationController (Additions)
- (UIViewController *)rootViewController;
@end
@implementation UINavigationController (Additions)
- (UIViewController *)rootViewController
{
return self.viewControllers.firstObject;
}
@end
Ответ 6
Как насчет запроса UIApplication singleton для keyWindow, и из этого UIWindow попросите контроллер корневого представления (свойство rootViewController):
UIViewController root = [[[UIApplication sharedApplication] keyWindow] rootViewController];
Ответ 7
Здесь я придумал универсальный метод навигации из любого места в корень.
-
Вы создаете новый файл класса с этим классом, чтобы он был доступен из любого места вашего проекта:
import UIKit
class SharedControllers
{
static func navigateToRoot(viewController: UIViewController)
{
var nc = viewController.navigationController
// If this is a normal view with NavigationController, then we just pop to root.
if nc != nil
{
nc?.popToRootViewControllerAnimated(true)
return
}
// Most likely we are in Modal view, so we will need to search for a view with NavigationController.
let vc = viewController.presentingViewController
if nc == nil
{
nc = viewController.presentingViewController?.navigationController
}
if nc == nil
{
nc = viewController.parentViewController?.navigationController
}
if vc is UINavigationController && nc == nil
{
nc = vc as? UINavigationController
}
if nc != nil
{
viewController.dismissViewControllerAnimated(false, completion:
{
nc?.popToRootViewControllerAnimated(true)
})
}
}
}
-
Использование в любом месте вашего проекта:
{
...
SharedControllers.navigateToRoot(self)
...
}