14

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

Matt Price
  • 34,499
  • 6
  • 24
  • 33

3 Answers3

31

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
Aayush
  • 1,244
  • 5
  • 19
  • 48
Samyukt Shah
  • 1,337
  • 12
  • 13
  • why giving error saying "existing instance variable" on creating id delegate and property delegate.? thanks. – MRizwan33 Feb 23 '18 at 09:22
1

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
Eimantas
  • 48,927
  • 17
  • 132
  • 168
  • Thanks Elimantas, Tried to implement this but failed! Is this true protocol and delegate implementation? I don't see @protocol and also . Do you have this code in xcode? or did you just write this straight into the answerbox? – Matt Price Mar 09 '11 at 11:42
  • It's not from xcode. Its straight into answer box. For this code to work - you don't need a protocol (unless you want clean code without gcc warnings). What do you mean by "failed!"? Wasn't the method called? I'll update the code with custom setter. – Eimantas Mar 09 '11 at 11:55
  • I get this: error: expected specifier-qualifier-list before 'returnedProperty' for this line @property returnedProperty=_returnedProperty; – Matt Price Mar 09 '11 at 12:36
0

You can use storyboard its quite easy. Use this in the implementation of SecondViewController and create a property in VIewController.h (The first view's controller) named dataFromSecondView

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
  NSString *textvalue = self.SecondViewText.text;
  ViewController *destination = segue.destinationViewController;
  destination.dataFromSecondView = textvalue;
}
VMAtm
  • 27,943
  • 17
  • 79
  • 125
Sudheesh
  • 483
  • 6
  • 20