it-swarm.com.ru

Как мне получить RootViewController от выдвинутого контроллера?

Итак, я выдвигаю контроллер представления из RootViewController как:

 [self.navigationController pushViewController: еще один анимированный просмотрщик: YES]; 

НО, ОТ anotherViewController теперь я хочу снова получить доступ к RootViewController.

Я пытаюсь

 // (теперь внутри другого ViewController) 
 /// RootViewController * root = (RootViewController *) self.parentViewController; // №. 
 // err 
 RootViewController * root = (RootViewController *) [self.navigationController.viewControllers objectAtIndex: 0]; // ДА!! оно работает

Я не уверен, ПОЧЕМУ это работает, и я не уверен, что это лучший способ сделать это. Может кто-нибудь прокомментировать лучший способ получить RootViewController от контроллера, который вы вставили в навигационный контроллер этого RootViewController, и является ли способ, которым я это сделал, надежным или нет?

132
bobobobo

Используйте свойство viewControllers UINavigationController. Пример кода:

// Inside another ViewController
NSArray *viewControllers = self.navigationController.viewControllers;
UIViewController *rootViewController = [viewControllers objectAtIndex:viewControllers.count - 2];

Это стандартный способ получить "задний" вид контроллера. Причина, по которой работает objectAtIndex:0, заключается в том, что контроллер представления, к которому вы пытаетесь получить доступ, также является корневым. Если бы вы были глубже в навигации, вид сзади не был бы таким же, как корневой вид.

130
Ben S

Swift версия:

var rootViewController = self.navigationController?.viewControllers.first

Версия ObjectiveC:

UIViewController *rootViewController = [self.navigationController.viewControllers firstObject];

Где self - это экземпляр UIViewController, встроенный в UINavigationController.

165
dulgan

Немного менее уродливая версия того же самого, упомянутого в почти всех этих ответах:

UIViewController *rootViewController = [[self.navigationController viewControllers] firstObject];

в вашем случае я бы, наверное, сделал что-то вроде:

внутри вашего подкласса UINavigationController:

- (UIViewController *)rootViewController
{
    return [[self viewControllers] firstObject];
}

тогда вы можете использовать:

UIViewController *rootViewController = [self.navigationController rootViewController];

Правка

ОП попросил недвижимость в комментариях.

если хотите, вы можете получить к нему доступ через что-то вроде self.navigationController.rootViewController, просто добавив свойство readonly в свой заголовок:

@property (nonatomic, readonly, weak) UIViewController *rootViewController;
12
Jesse

Для всех, кто интересуется расширением Swift, это то, что я сейчас использую:

extension UINavigationController {
    var rootViewController : UIViewController? {
        return self.viewControllers.first as? UIViewController
    }
}
7
csch

В качестве дополнения к ответу @ dulgan's всегда полезно использовать 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
3
ozgur

Как насчет запроса IApplicationsingleton для его keyWindow , и из этого IWindow запросить корневой контроллер представления (его rootViewController свойство):

UIViewController root = [[[UIApplication sharedApplication] keyWindow] rootViewController];
1
Basil Bourque

Здесь я придумал универсальный способ навигации из любого места в root.

  1. Вы создаете новый файл Class с этим классом, чтобы он был доступен из любого места в вашем проекте:

    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)
                })
            }
        }
    }
    
  2. Использование из любой точки вашего проекта:

    {
        ...
        SharedControllers.navigateToRoot(self)
        ...
    }
    
1
Maris