RootViewController'ı itilen bir denetleyiciden nasıl alabilirim?


137

Yani, RootViewController gibi bir görünüm denetleyicisi itmek gibi:

[self.navigationController pushViewController: animasyonlu başka birViewController: YES];

AMA, anotherViewControllerŞİMDİ, tekrar RootViewController erişmek istiyorum.

deniyorum

// (şimdi anotherViewController içinde)
/// RootViewController * root = (RootViewController *) self.parentViewController; // Hayır.
// hata
RootViewController * root = (RootViewController *) [self.navigationController.viewControllers objectAtIndex: 0]; // EVET!! işe yarıyor

NEDEN bu işe yarıyor emin değilim ve bunu yapmak için en iyi yolu emin değilim. Birisi RootViewController'ın bu RootViewController'ın navigationController'ına aktardığınız bir denetleyiciden RootViewController'ı almanın daha iyi bir yolu hakkında yorum yapabilir ve yaptığım yolun güvenilir olup olmadığını düşünebilir mi?


Yaptığınız şey kök görünüm denetleyicisini (gezinme hiyerarşisinde ilk olan) güvenilir bir şekilde alacaktır, "arka" görünüm denetleyicisine erişmek istiyorsanız, cevabımı görün.
Ben S

Yanıtlar:


133

UINavigationController öğesinin viewControllers özelliğini kullanın . Örnek kod:

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

Bu, "arka" görüntü denetleyicisini almanın standart yoludur. Bunun nedeni objectAtIndex:0, erişmeye çalıştığınız görünüm denetleyicisinin de kök olması, navigasyonda daha derin olmanız durumunda arka görünümün kök görünümüyle aynı olmamasıdır.


6
:) ty. Hala hacky görünüyor - :) Gerçekten bir "resmi" üye, self.navigationController.rootViewController gibi bir şey yapmak istedim, ama ne yazık ki, böyle bir şey ..
bobobobo

62
Yukarıdaki kod hatalı. önce rootViewControllereksik *ve dizin sadece olmalıdır 0. RootViewController *root = (RootViewController *)[navigationController.viewControllers objectAtIndex:0]
Sorudaki

2
Kabul edildi: yukarıdaki kod , OP'nin istediği gibi kök görünüm denetleyicisini değil, üst görünüm denetleyicisini döndürür . Yine de, Ben S'nin yapacağını söyledi, bunu yeterince işaret etmedi.
Ivan Vučica

2. satır şunu okumalıdır: UIViewController * rootViewController = [viewControllers objectAtIndex: viewControllers.count - 1];
Billy

177

Hızlı sürüm:

var rootViewController = self.navigationController?.viewControllers.first

ObjectiveC sürümü:

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

Burada self, bir UINavigationController içine gömülü bir UIViewController örneğidir.


Başka bir ViewController'ın navigationController'ı farklı bir sınıftan alabilir miyim?
sasquatch

Herhangi bir UIViewController alt sınıfı, UINavigationController sınıfıyla eşleşen ilk parentViewController öğesini gösteren bir navigationController özelliğine sahiptir.
dulgan

12

Hemen hemen tüm bu cevaplarda aynı şeyin biraz daha az çirkin bir versiyonu:

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

senin durumunda, muhtemelen şöyle bir şey yapardım:

UINavigationController alt sınıfınızın içinde :

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

o zaman kullanabilirsiniz:

UIViewController *rootViewController = [self.navigationController rootViewController];

Düzenle

OP yorumlarda bir özellik istedi.

isterseniz, self.navigationController.rootViewControllerbaşlığınıza salt okunur bir özellik ekleyerek buna benzer bir şeyle erişebilirsiniz :

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

8

Hızlı bir uzantı ile ilgilenen herkes için, şu anda kullandığım şey bu:

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

1
Teşekkürler! Ayrıca "as? UIViewController"
atereshkov

3

@ Dulgan'ın cevabına ek olarak , her zaman firstObjectüzerinde kullanmak iyi bir yaklaşımdır objectAtIndex:0, çünkü dizide hiçbir nesne yoksa birincisi nil döndürürken, ikincisi istisna atar.

UIViewController *rootViewController = self.navigationController.rootViewController;

Alternatif olarak, adında bir kategori oluşturmanız UINavigationController+Additionsve yönteminizi tanımlamanız sizin için büyük bir artı olacaktır .

@interface UINavigationController (Additions)

- (UIViewController *)rootViewController;

@end

@implementation UINavigationController (Additions)

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

@end

Ben sadece cevabınızı okumadan bu bölümü ekledim, "firstObject" daha iyi olmaktan tamamen haklısın [0]
dulgan


1

Burada herhangi bir yerden köke gitmek için evrensel bir yöntem buldum.

  1. Projenizdeki herhangi bir yerden erişilebilir olması için bu sınıfla yeni bir Sınıf dosyası oluşturursunuz:

    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. Projenizin herhangi bir yerinden kullanım:

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

0

Bu benim için çalıştı:

Kök görünüm denetleyicim bir gezinme denetleyicisine katıştırıldığında:

UINavigationController * navigationController = (UINavigationController *)[[[[UIApplication sharedApplication] windows] firstObject] rootViewController];
RootViewController * rootVC = (RootViewController *)[[navigationController viewControllers] firstObject];

Unutulmadığını unutmayın keyWindow.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.