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
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
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
The same question has been answered over here:
Pass a variable between lots of UIVIewControllers
Hope this will be the easy & sufficient one .....
I ended up using this example
Sharing data between view controllers and other objects @ iPhone Dev SDK
Worked fine and allowed me to pass a string and an array forward and back between my views.
Thanks for all your help
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;
}