1

Dear fellow programmers,

What is the best way to pass information from a child in a navigation stack up one or more levels? I have searched online and can't seem to find the best way to begin implementing this.

Specifically this is my model: I have a grouped table view with several rows. When a user clicks on a row I take them to an MVC .ie click on 'select date' row takes them to a MVC with a datepicker setup (the parent passes data to the child in the process). Once this date picker (or other piece of data) has been selected, how do I pass the data back? Heres some code of the setup if it helps:

/* following is inside didSelectRowAtIndexPath of parent in navigation stack */

if (row == 1) {
    DateViewController *datevc = [[DateViewController alloc] init];
    datevc.selectedDate = [self dateToEnter];
    [self.navigationController pushViewController:datevc animated:YES;
    [datevc release];
}

DateViewController.h

#import <UIKit/UIKit.h>

@interface EnterProcedureDateViewController : UIViewController {
    IBOutlet UIDatePicker *datePicker;
    NSDate *selectedDate;
}

@property (nonatomic, retain) IBOutlet UIDatePicker *datePicker;
@property (nonatomic, retain) NSDate *selectedDate;

-(IBAction)selectButtonPressed:(id)sender;

@end

DateViewController.m

#import "DateViewController.h"

@implementation EnterProcedureDateViewController

@synthesize datePicker;
@synthesize selectedDate;

-(IBAction)selectButtonPressed:(id)sender {

    /* how do I pass the date pickers date back to the ivar dateToEnter of parent?? */

    [self.navigationController popViewControllerAnimated:YES];
}

-(void)viewWillAppear:(BOOL)animated {
    if (selectedDate == nil) {
        datePicker.date = [NSDate date];
    } else {
        datePicker.date = selectedDate;
    }
    [super viewWillAppear:animated];
}

...

@end

Thanks in advance as always

Andy

Andy
  • 717
  • 1
  • 9
  • 24

4 Answers4

4

UINavigationController has a property, viewControllers, which returns an NSArray of all the view controllers in the stack.

The "parent" view controller (i.e. the one below your currently visible one) can be obtained by:

TableViewController *parentViewController = (TableViewController*)[self.navigationController.viewControllers objectAtIndex:self.navigationController.viewControllers.count - 2];

You can then call any methods or set properties as required.

jrturton
  • 118,105
  • 32
  • 252
  • 268
4

In call backs, one of the best and recommended ways to do it is Delegates.

In your case, you will need to create a DataViewControllerDelegate and put here all the methods that Delegates of this class can call. Now, the parent should implement this delegate and register itself as the delegate when initializing it.

It's better with an example, take a look at Jonathan's answer on making custom delegates.

Community
  • 1
  • 1
mohdajami
  • 9,604
  • 3
  • 32
  • 53
  • thanks medopal. i have been doing a lot of reading around this and thought that the protocol/delegates approach was the way forward but wasn't sure. to clarify...do I create the 'DataViewController' as a protocol, and then have both the MVC classes (the tableview class[parent] and EnterProcedureDateViewController[child] - as in code above) conform to this protocol, with only the tableview set as delegate? – Andy Sep 12 '11 at 14:08
1

Something like this?

I can't see all of your code structure, so I've made some assumptions about inheritance and class structure.

Get's the view of the parent view controller, casts it to the appropriate subclass of UIView and passes a message to it.

[((MayNeedCastToSpecificClass*)[self.view parentViewController].view) setMyDate:date];
James Webster
  • 31,873
  • 11
  • 70
  • 114
0

in your parentviewcontroller add the property

   @property (nonatomic, retain) NSDate *selectedDate;

in childViewController after selecting the date

parentViewController *parentViewController =[self.navigationController.viewControllers objectAtIndex:self.navigationController.viewControllers.count - 2];
parentViewController.selectedDate = self.selectedDate;
[self.navigationController popViewControllerAnimated:YES];

then you can access the property from parentviewcontroller

Rashid
  • 829
  • 7
  • 6