Using a delegate to pass data back up the navigation stack

20,161

Solution 1

Delegation is the correct pattern to be used in this case, but your description doesn't look much like delegation as it is using a global variable. Perhaps you're storing global variables in your App Delegate which you should always try to avoid.

Here's a rough outline of what the code should look like:

SecondViewController.h:

@protocol SecondViewControllerDelegate;

@interface SecondViewController;

SecondViewController : UIViewController
{
    id<SecondViewControllerDelegate> delegate;

    NSArray* someArray;
}

@property (nonatomic, assign) id<SecondViewControllerDelegate> delegate;
@property (nonatomic, retain) NSArray* someArray;

@end

@protocol SecondViewControllerDelegate
- (void)secondViewControllerDidFinish:(SecondViewController*)secondViewController;
@end

SecondViewController.m:

@implementation SecondViewController

@synthesize delegate;
@synthesize someArray;

- (void)dealloc
{
    [someArray release];
    [super dealloc];
}

- (void)someMethodCalledWhenUserIsDone
{
    [delegate secondViewControllerDidFinish:self];
}

FirstViewController.h:

#import SecondViewController

@interface FirstViewController : UIViewController <SecondViewControllerDelegate>
{
    ...
}

@end

FirstViewController.m:

@implementation FirstViewController

- (void)secondViewControllerDidFinish:(SecondViewController*)secondViewController
{
    NSArray* someArray = secondViewController.someArray
    // Do something with the array
}

@end

Solution 2

Off top of my head. You can replace _returnedProperty with your custom object and in setReturnedProperty method do all the magic before actually assigning the checked value from the table.

@interface FormController : UIViewController {
    NSString *_returnedProperty;
}

@property (nonatomic, retain) NSString *returnedProperty;

@end

@implementation FormController

- (void)showChoices {
    TableController *tv = [[TableController alloc] initWithDelegate:self];
    [self.navigationController pushViewController:tv animated:YES];
    [tv release];
}

- (void)setReturnedProperty:(NSString *)string {
    NSLog(@"Setting property as a delegate");
    [_returnedProperty release];
    _returnedProperty = [string retain];
}

@synthesize returnedProperty=_returnedProperty;

@end

@interface TableController : UITableViewController {
    id _delegate
}
@end

@implementation TableController

- (id)initWithDelegate:(id)delegate {
    self = [super initWithStyle:UITableViewGroupedStyle];
    if (!self) return nil;

    _delegate = delegate;
    return self;
}

- (void)tableView:(UITableView *)tv didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    // do the data retrieval stuff
    NSString *returnedProperty = @"foo";
    [_delegate setReturnedProperty:returnableProperty];
}

@end
Share:
20,161
Matt Price
Author by

Matt Price

Updated on July 22, 2020

Comments

  • Matt Price
    Matt Price almost 4 years

    I have been battling with passing data between two view controllers for a couple of days now and getting very confused. I'm new to Objective-C and finding some parts tricky to get my head round.

    I have a Navigation Controller, FirstView is a form and on this form I have a button which loads SecondView which contains a TableView for the user to select some options. I then want to pass the selection back to the FirstView controller and display the data etc...

    I have read alot about this (stackoverflow, iphonedevsdk, CS 193P Resources) and the options i've seen are,

    1) ivar in app delegate (dirty and not recommended) 2) create a singleton 3) create a data model class 4) Use protocols and delegates (recommended by apple)

    I want to do things right and want to use option 4 - Delegates in my program

    Problem is, I don't understand delegates and how to setup and implement them.

    Could anyone provide a basic example on how to setup and pass an NSArray using the delegate and 2 view controllers.

    Thanks in advance Matt