7

Currently I add a viewcontroller using pushViewController:animated: and now from within that new one would like to call a method inside my "parent"-controller. I think I get stuck at the navigationcontroller.

Currently trying this to see if it's the controller I want:

if([self.superclass isKindOfClass:[MySuperController class]])
// and tried:
if([self.presentingViewController isKindOfClass:[MySuperController class]])

None of these two worked.

How can I access the controller (a method in it) that pushed the current one?

Pangolin
  • 7,284
  • 8
  • 53
  • 67

3 Answers3

37

Just like Marsson mentioned, you need to use delegate...

Here is an sample:

In your child view controller .h file:

@protocol ChildViewControllerDelegate <NSObject>
- (void)parentMethodThatChildCanCall;
@end

@interface ChildViewController : UIViewController 
{
}
@property (assign) id <ChildViewControllerDelegate> delegate;

In your child view controller .m file:

@implementation ChildViewController
@synthesize delegate;


// to call parent method:
//  [self.delegate parentMethodThatChildCanCall];

In parent view controller .h file:

@interface parentViewController <ChildViewControllerDelegate>

In parent view controller .m file:

//after create instant of your ChildViewController
childViewController.delegate = self;

- (void) parentMethodThatChildCanCall
{
  //do thing
}
user523234
  • 14,323
  • 10
  • 62
  • 102
  • Yay! Thanks :D - I called the method in the child using `[self.delegate myMethod];` – Pangolin Nov 08 '11 at 19:01
  • I've been struggling with this all day until I found this answer. Forgot to set the childviewcontroller delegate to self. Thanks for the answer :-). – Holger Sindbaek Nov 16 '12 at 03:38
4
self.navigationController.viewControllers

Returns an array of all the view controllers in the navigation stack. The current view controller is at the top of the stack, the previous view controller is the next one down, and so forth.

So, you can do the following:

NSArray *viewControllers =     self.navigationController.viewControllers;
int count = [viewControllers count];
id previousController = [viewControllers objectAtIndex:count - 2];
if ([previousController respondsToSelector:@selector(myMethod)])
    [previousController myMethod];

If you know what class the previous controller is you can cast it explicity instead of using id.

jrturton
  • 118,105
  • 32
  • 252
  • 268
  • Seems like a legit way, but, `count` is `0` when I `NSLog` it. – Pangolin Nov 08 '11 at 18:53
  • That would suggest the navigationcontroller was nil, I did assume you were using a navigation controller from the question, is that wrong? – jrturton Nov 08 '11 at 20:43
1

Not sure of your application logic, but you can always do this.

In your "child" controller, declare property of type parent-controller. So, in your .h file:

MySuperController *superController;
property(nonatomic, retain)MysuperController *superController;

and in your .m file:

@synthesize superController;

Before "pushing" your child controller:

MyChildController *child = ...
[child setSuperController:self];
[self.navigationController pushViewController:child animated:YES];

Then in your child controller you can simply access your super with

[this.superController myMethod:param];

I'm not going to advocate this way of coding, but it's a quick/cheap/dirty way to accomplish things.

Aleks G
  • 56,435
  • 29
  • 168
  • 265
  • Cool, thanks. Just when I try `[child setSuperController:self];` it warns about me trying to send `MySuperController*` instead of `int *` ... weird? – Pangolin Nov 08 '11 at 18:38
  • Ah, cant do this. It creates infinite loop. (With them importing each other) – Pangolin Nov 08 '11 at 18:45