Jadi, saya mendorong pengontrol tampilan dari RootViewController seperti:
[self.navigationController pushViewController: anotherViewController animasi: YES];
TAPI, DARI anotherViewController
sekarang, saya ingin mengakses RootViewController lagi.
Saya mencoba
// (di dalam anotherViewController sekarang) /// RootViewController * root = (RootViewController *) self.parentViewController; // Tidak. // err RootViewController * root = (RootViewController *) [self.navigationController.viewControllers objectAtIndex: 0]; // IYA!! berhasil
Saya tidak yakin MENGAPA ini berhasil dan saya tidak yakin apakah itu cara terbaik untuk melakukannya. Adakah yang bisa memberi komentar tentang cara yang lebih baik untuk mendapatkan RootViewController dari pengontrol yang Anda dorong ke navigationController RootViewController dan apakah cara yang saya lakukan dapat diandalkan atau tidak?
ios
iphone
uinavigationcontroller
bobobobo
sumber
sumber
Jawaban:
Gunakan properti viewControllers dari UINavigationController. Kode contoh:
// Inside another ViewController NSArray *viewControllers = self.navigationController.viewControllers; UIViewController *rootViewController = [viewControllers objectAtIndex:viewControllers.count - 2];
Ini adalah cara standar untuk mendapatkan pengontrol tampilan "belakang". Alasan
objectAtIndex:0
berfungsi adalah karena pengontrol tampilan yang Anda coba akses juga merupakan root, jika Anda lebih dalam di navigasi, tampilan belakang tidak akan sama dengan tampilan root.sumber
rootViewController
hilang*
sebelumnya, dan indeks seharusnya0
. Kode dalam pertanyaan benar:RootViewController *root = (RootViewController *)[navigationController.viewControllers objectAtIndex:0]
Versi Swift:
var rootViewController = self.navigationController?.viewControllers.first
Versi ObjectiveC:
UIViewController *rootViewController = [self.navigationController.viewControllers firstObject];
Di mana self adalah turunan dari UIViewController yang disematkan dalam UINavigationController.
sumber
Versi yang sedikit lebih jelek dari hal yang sama disebutkan dalam hampir semua jawaban ini:
UIViewController *rootViewController = [[self.navigationController viewControllers] firstObject];
dalam kasus Anda, saya mungkin akan melakukan sesuatu seperti:
di dalam subkelas UINavigationController Anda :
- (UIViewController *)rootViewController { return [[self viewControllers] firstObject]; }
maka Anda dapat menggunakan:
UIViewController *rootViewController = [self.navigationController rootViewController];
edit
OP meminta properti di komentar.
jika Anda mau, Anda dapat mengaksesnya melalui sesuatu seperti
self.navigationController.rootViewController
hanya dengan menambahkan properti readonly ke header Anda:@property (nonatomic, readonly, weak) UIViewController *rootViewController;
sumber
Untuk semua yang tertarik dengan ekstensi cepat, inilah yang saya gunakan sekarang:
extension UINavigationController { var rootViewController : UIViewController? { return self.viewControllers.first } }
sumber
Sebagai tambahan @ dulgan ini jawabannya, itu selalu merupakan pendekatan yang baik untuk menggunakan
firstObject
lebihobjectAtIndex:0
, karena sementara yang pertama kembali nil jika tidak ada objek dalam array, satu yang terakhir melempar pengecualian.UIViewController *rootViewController = self.navigationController.rootViewController;
Atau, akan menjadi nilai tambah yang besar bagi Anda untuk membuat kategori bernama
UINavigationController+Additions
dan menentukan metode Anda di dalamnya .@interface UINavigationController (Additions) - (UIViewController *)rootViewController; @end @implementation UINavigationController (Additions) - (UIViewController *)rootViewController { return self.viewControllers.firstObject; } @end
sumber
Bagaimana jika meminta UIApplication singleton untuk keyWindow - nya , dan dari UIWindow tersebut meminta pengontrol tampilan root ( properti rootViewController -nya ):
UIViewController root = [[[UIApplication sharedApplication] keyWindow] rootViewController];
sumber
Di sini saya menemukan metode universal untuk menavigasi dari tempat mana pun ke root.
Anda membuat file Kelas baru dengan kelas ini, sehingga dapat diakses dari mana saja dalam proyek Anda:
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) }) } } }
Penggunaan dari mana saja dalam proyek Anda:
{ ... SharedControllers.navigateToRoot(self) ... }
sumber
Ini berhasil untuk saya:
Ketika pengontrol tampilan root saya tertanam di pengontrol navigasi:
UINavigationController * navigationController = (UINavigationController *)[[[[UIApplication sharedApplication] windows] firstObject] rootViewController]; RootViewController * rootVC = (RootViewController *)[[navigationController viewControllers] firstObject];
Ingat itu
keyWindow
sudah usang.sumber
Saya mengalami kondisi yang aneh.
self.viewControllers.first
bukan root viewController selalu.Secara umum,
self.viewControllers.first
memang root viewController. Tapi terkadang tidak.class MyCustomMainNavigationController: UINavigationController { function configureForView(_ v: UIViewController, animated: Bool) { let root = self.viewControllers.first let isRoot = (v == root) // Update UI based on isRoot // .... } } extension MyCustomMainNavigationController: UINavigationControllerDelegate { func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) { self.configureForView(viewController, animated: animated) } }
Masalah saya:
Umumnya,
self.viewControllers.first
adalahroot
viewController. Tapi, saat saya meneleponpopToRootViewController(animated:)
, lalu terpicunavigationController(_:willShow:animated:)
. Saat ini,self.viewControllers.first
BUKAN root viewController, ini adalah viewController terakhir yang akan menghilang.Ringkasan
self.viewControllers.first
tidak selaluroot
viewController. Terkadang, ini akan menjadi viewController terakhir.Jadi, saya sarankan untuk tetap
rootViewController
menggunakan properti ketikaself.viewControllers
HANYA memiliki satu viewController. Saya mendapatkan root viewController diviewDidLoad()
UINavigationController kustom.class MyCustomMainNavigationController: UINavigationController { fileprivate var myRoot: UIViewController! override func viewDidLoad() { super.viewDidLoad() // My UINavigationController is defined in storyboard. // So at this moment, // I can get root viewController by `self.topViewController!` let v = self.topViewController! self.myRoot = v } }
Lingkungan:
sumber