Làm cách nào để có được RootViewContaptor từ bộ điều khiển đẩy?


137

Vì vậy, tôi đẩy một bộ điều khiển xem từ RootViewControll như:

[self.navestionControll PushViewCont điều khiển: AnotherViewControll hoạt hình: CÓ];

NHƯNG, TỪ anotherViewControllerbây giờ, tôi muốn truy cập lại RootViewControll.

Tôi đang cô

// (bên trong otherViewControll bây giờ)
/// RootViewControll * root = (RootViewControll *) self.parentViewControll; // Không.
// lỗi
RootViewControll * root = (RootViewControll *) [self.navlationControll.viewControllers objectAtIndex: 0]; // ĐÚNG!! nó hoạt động

Tôi không chắc chắn TẠI SAO điều này hoạt động và tôi không chắc đó là cách tốt nhất để làm điều đó. Ai đó có thể nhận xét về một cách tốt hơn để có được RootViewContoder từ bộ điều khiển mà bạn đã đẩy vào điều hướng điều khiển của RootViewContaptor và liệu cách tôi đã thực hiện có đáng tin hay không?


Những gì bạn đã làm sẽ có được bộ điều khiển xem gốc (cái đầu tiên trong hệ thống phân cấp điều hướng), nếu bạn muốn có quyền truy cập vào bộ điều khiển xem "quay lại", hãy xem câu trả lời của tôi.
Ben S

Câu trả lời:


133

Sử dụng thuộc tính viewControllers của UINavestionControll. Mã ví dụ:

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

Đây là cách tiêu chuẩn để có được bộ điều khiển xem "quay lại". Lý do objectAtIndex:0hoạt động là vì trình điều khiển chế độ xem bạn đang cố truy cập cũng là trình điều khiển gốc, nếu bạn ở sâu hơn trong điều hướng, chế độ xem lại sẽ không giống với chế độ xem gốc.


6
:) ty. Nó vẫn có vẻ hacky - :) Tôi thực sự muốn một thành viên "chính thức" thực hiện công việc, một cái gì đó như self.navlationContoder.rootViewContoder, nhưng than ôi, không có điều đó ..
bobobobo

62
Các mã trên là sai. rootViewControllerbị thiếu *trước nó, và chỉ số nên được 0. Mã trong câu hỏi là chính xác:RootViewController *root = (RootViewController *)[navigationController.viewControllers objectAtIndex:0]
ma11hew28

2
Đồng ý: đoạn mã trên trả về bộ điều khiển khung nhìn cha , không phải bộ điều khiển khung nhìn gốc như OP yêu cầu. Tuy nhiên, đó là những gì Ben S nói anh ấy sẽ làm, anh ấy đã không chỉ ra điều đó đủ.
Ivan Vučica

Dòng thứ 2 nên đọc: UIViewControll * rootViewControll = [viewControllers objectAtIndex: viewControllers.count - 1];
Billy

177

Phiên bản Swift:

var rootViewController = self.navigationController?.viewControllers.first

Phiên bản ObjectiveC:

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

Trong đó bản thân là một phiên bản của UIViewControll được nhúng trong UINavestionControll.


Tôi có thể lấy navigationContoder của một ViewContoder khác từ một lớp khác không?
sasquatch

Bất kỳ lớp con UIViewControll nào cũng sẽ có thuộc tính navigationContoder, nó trỏ đến lớp chaViewControll đầu tiên của nó phù hợp với lớp UINavestionControll.
dulgan

12

Một phiên bản ít xấu xí hơn của cùng một điều được đề cập trong hầu hết các câu trả lời sau:

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

trong trường hợp của bạn, tôi có thể làm một cái gì đó như:

bên trong lớp con UINavestionControll của bạn :

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

sau đó bạn có thể sử dụng:

UIViewController *rootViewController = [self.navigationController rootViewController];

biên tập

OP yêu cầu một tài sản trong các ý kiến.

nếu bạn thích, bạn có thể truy cập thông qua thứ này giống như self.navigationController.rootViewControllerchỉ cần thêm thuộc tính chỉ đọc vào tiêu đề của bạn:

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

8

Đối với tất cả những ai quan tâm đến tiện ích mở rộng nhanh chóng, đây là những gì tôi đang sử dụng:

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

1
Cảm ơn! Ngoài ra, bạn có thể xóa "as? UIViewControll"
atereshkov

3

Như một sự bổ sung để @ dulgan của câu trả lời, nó luôn luôn là một phương pháp tốt để sử dụng firstObjecttrên objectAtIndex:0, vì trong khi người đầu tiên trở về NIL nếu không có đối tượng trong mảng, một thứ hai ném ngoại lệ.

UIViewController *rootViewController = self.navigationController.rootViewController;

Ngoài ra, đó là một điểm cộng lớn cho bạn để tạo một danh mục có tên UINavigationController+Additionsvà xác định phương thức của bạn theo đó.

@interface UINavigationController (Additions)

- (UIViewController *)rootViewController;

@end

@implementation UINavigationController (Additions)

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

@end

Tôi chỉ thêm phần này mà không cần đọc câu trả lời của bạn, bạn hoàn toàn đúng với "FirstObject" trở nên tốt hơn [0]
dulgan

1

Làm thế nào về việc hỏi đơn vị UIApplication cho keyWindow của nó và từ UIWindow đó yêu cầu bộ điều khiển xem gốc (thuộc tính rootViewControll của nó ):

UIViewController root = [[[UIApplication sharedApplication] keyWindow] rootViewController];

Làm thế nào để có được bộ điều khiển điều hướng?
Yestay Muratov

Đây là một gợi ý sai vì nếu trình điều khiển ứng dụng gốc của tôi là UITabBarViewCont kiểm soát thì sao?
Sandeep Singh Rana

1

Ở đây tôi đã đưa ra phương pháp phổ quát để điều hướng từ bất kỳ nơi nào để root.

  1. Bạn tạo một tệp Class mới với lớp này, để nó có thể truy cập từ mọi nơi trong dự án của bạn:

    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. Sử dụng từ bất cứ nơi nào trong dự án của bạn:

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

0

Điều này làm việc cho tôi:

Khi bộ điều khiển xem gốc của tôi được nhúng trong bộ điều khiển điều hướng:

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

Hãy nhớ rằng đó keyWindowlà phản đối.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.