Reputation: 2626
I'm presenting a ViewController modally. How can I access the parent view controller ?
My architecture is TabBarController=>VC1=>VC2=>VC3=>MVC1, and I want to reach VC3 from MVC1.
In VC3, I have this code :
- (void) editAd{
AskPasswordViewController *modalViewController = [[AskPasswordViewController alloc] initWithNibName:@"AskPasswordView" bundle:nil];
NSLog(@"modalparent class=%@", [[modalViewController parentViewController] class]);
[self presentModalViewController:modalViewController animated:YES];
[modalViewController release];
}
I tried this in MVC1:
- (void) sendRequest {
NSLog(@"classe : %@",[[self parentViewController] class] );
}
but it returns my TabBarViewController...
Upvotes: 31
Views: 33896
Reputation: 5954
If presentingViewController
gives you unexpected results and you don't want to fiddle with it, just do:
class MyViewController: UIViewController {
private weak var presenter: UIViewController?
init(presenter: UIViewController) {
self.presenter = presenter
super.init(nibName: nil, bundle: nil)
...
}
...
}
Upvotes: 0
Reputation: 71
Addition to Vibhor Goyal - Sometimes, self.presentingViewController registers as NavigationController. Therefore try:
if let vc = self.presentingViewController.childViewControllers.last as? YourViewController {
// do stuff here
}
Upvotes: 7
Reputation: 684
Here I came up with universal method to navigate from any place to root.
You create a new Class file with this class, so that it's accessible from anywhere in your project:
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)
})
}
}
}
Usage from anywhere in your project:
{
...
SharedControllers.navigateToRoot(self)
...
}
Upvotes: 1
Reputation: 591
//You have to get the root, iterate through the root's ViewControllers and then ask for the ParentViewController.
UINavigationController *root = (UINavigationController*)[[(AppDelegate*) [[UIApplication sharedApplication]delegate] window] rootViewController];
for (UIViewController *VC in root.viewControllers) {
if([VC isKindOfClass:[YourParentViewController class]]){
YourParentViewController* parent = (YourParentViewController*)VC;
[parent callMethod]; // your code here
[self dismissViewControllerAnimated:YES completion:nil];
}
}
Upvotes: 0
Reputation: 2425
You can access parent by calling:
self.presentingViewController
As per apple documentation:
The view controller that presented this view controller (or its farthest ancestor.)
Upvotes: 99
Reputation: 5831
The way I'd go about something like this is to simply create a delegate. In AskPasswordViewController
's header, put
id delegate;
and
@property (nonatomic, assign) id delegate;
Synthesize it in the implementation file. Then after you alloc/init the modal controller, and before you present it, set modalViewController.delegate = self;
. Then within the modal controller, you can call self.delegate
to get information from the view controller that presented it. I hope this helps
Upvotes: 25
Reputation: 9453
You can always go further back just by calling parentViewController like so:
self.parentViewController.parentViewController
.... and so on until you reach the right one.
Upvotes: 7