iOS passing data between View Controllers Example

Passing data is an everyday need if your app has more than one screen. Messages in Objective-C are a one-way street. A parent class can send a message to its child, but the child cannot. However, with the help of a delegate, two-way communication can be achieved.

So passing data forward from your first viewcontroller to the second view controller is pretty easy as the first viewcontroller has direct access to the second viewcontroller and it can just set the properties. But the other way around is not that simple and needs a little bit of an extra coding. To pass data between the viewcontrollers you have to define a protocol that will implement at least one method that we can use. The first viewcontroller then becomes a delegate for the second viewcontroller and must adhere to the protocol's required methods. Basically the delegate function becomes the callback method when the response comes back from the second view controller.

Here is an example where we create two viewcontrollers and pass data between each other. For the purpose of keeping the example simple we define our view programmatically adding a few text fields and a button on the screens. The navigation controller displays the first view and then when the user clicks on the button it passes the data from the first view to the second view and if the user clicks on the back button of the navigation controller it calls the setScreenValues method defined in the protocol to pass the information back to the first screen. In the example we pass an object but you can pass simple String and integers using multiple parameters in the delegate method.

iOS passing data between View Controllers Example
iOS passing data First View Controller
iOS passing data Second View Controller
Create a new Project to create an iOS application with template as Empty Application. In the Product Name and Class prefix enter PassingData. Check the box Use Automatic Reference Counting (ARC) and then choose where you want to create your project.

iOS passing data between View Controllers create Project

Interface file for the application delegate - PassingDataAppDelegate.h

#import <UIKit/UIKit.h>
#import "FirstViewController.h"

@interface PassingDataAppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;
@property (nonatomic, retain) UINavigationController    *navigationController;
@property (nonatomic, retain) FirstViewController       *firstViewController;

@end

Implementation file for the application delegate - PassingDataAppDelegate.m

#import "PassingDataAppDelegate.h"

@implementation PassingDataAppDelegate
@synthesize navigationController, firstViewController;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    
    //create the navigation controller and add to the view
    navigationController = [[UINavigationController alloc] init];
    [self.window addSubview:[self.navigationController view]];
    
    //check if the first viewcontroller eixsts, otherwise create it
    if(self.firstViewController == nil)
    {
        FirstViewController *firstView = [[FirstViewController alloc] init];
        self.firstViewController = firstView;
    }
    
    //push the first viewcontroller into the navigation viewcontroller stack
    [self.navigationController pushViewController:self.firstViewController animated:YES];
    
    
    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];
    return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application
{
    //do nothing
}

- (void)applicationDidEnterBackground:(UIApplication *)application
{
     //do nothing
}

- (void)applicationWillEnterForeground:(UIApplication *)application
{
     //do nothing
}

- (void)applicationDidBecomeActive:(UIApplication *)application
{
     //do nothing
}

- (void)applicationWillTerminate:(UIApplication *)application
{
     //do nothing
}

@end

Interface file for Country Object - Country.h

#import <Foundation/Foundation.h>

@interface Country : NSObject

@property NSString *code;
@property NSString *name;

@end

Implementation file for Country Object - Country.h

#import "Country.h"

@implementation Country

@synthesize code, name;

@end

Interface file for First View Controller - FirstViewController.h

#import <UIKit/UIKit.h>
#import "SecondViewController.h"
#import "Country.h"

//implements the second viewcontrollers "PassInformation" protocol
@interface FirstViewController : UIViewController <PassInformation>

@property (nonatomic, retain) SecondViewController *secondViewController;
@property Country *country;

@property UITextField *countryCode;
@property UITextField *countryName;

@end

Implementation file for First View Controller - FirstViewController.m


#import "FirstViewController.h"

@interface FirstViewController ()

@end

@implementation FirstViewController

@synthesize countryCode,countryName;
@synthesize country;
@synthesize secondViewController;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
        country = [[Country alloc] init];
        
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    NSLog(@"First view did load");
 // Do any additional setup after loading the view.
    
    //set the title of the navigation view
    [self.navigationItem setTitle:@"First View"];
    
    //set the background color of the view
    [self.view setBackgroundColor:[UIColor lightGrayColor]];
    
    //create a text field for our country code and add to the view
    countryCode = [[UITextField alloc] init];
    [countryCode setBorderStyle: UITextBorderStyleRoundedRect];
    [countryCode setFrame:CGRectMake(10.0,10.0,200.0,30.0)];
    [countryCode setPlaceholder:@"Enter Country Code here"];
    [self.view addSubview: countryCode];
    
    //create a text field for our country name and add to the view
    countryName = [[UITextField alloc] init];
    [countryName setBorderStyle: UITextBorderStyleRoundedRect];
    [countryName setFrame:CGRectMake(10.0,50.0,200.0,30.0)];
    [countryName setPlaceholder:@"Enter Country Name here"];
    [self.view addSubview: countryName];
    
    //create a button so that when user clicks we can go to the next view
    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    [button addTarget:self
            action:@selector(goToNextView:)
            forControlEvents:UIControlEventTouchDown];
    [button setTitle:@"Next View" forState:UIControlStateNormal];
    [button setBackgroundColor:[UIColor darkGrayColor]];
    button.frame = CGRectMake(10.0, 90.0, 200.0, 30.0);
    [self.view addSubview:button];
    
    
    
}

//action method linked to the button, gets called on the touchdown event
- (void) goToNextView:(id)sender {
    
    //get reference to the button that requested the action
    UIButton *button = (UIButton *)sender;
    
    //check which button it is, if you have more than one button on the screen
    //you must check before taking necessary action
    if([button.currentTitle isEqualToString:@"Next View"]){
        NSLog(@"Clicked on the button");
        
        //if the second view controller doesn't exists create it
        if(self.secondViewController == nil){
            SecondViewController *secondView = [[SecondViewController alloc] init];
            self.secondViewController = secondView;
        }
        
        //set this view as the second viewcobntroller's delegate so that it can listen for events
        [secondViewController setDelegate:self];
        
        //save the country object with screen values
        country.code = countryCode.text;
        country.name = countryName.text;
        
        //set the country object of the second view controller
        [self.secondViewController setCountry:country];
        
        //tell the navigation controller to push a new view into the stack
        [self.navigationController pushViewController:self.secondViewController animated:YES];
        
    }
    
}

//before the view appears check the country object and set the screen values
- (void) viewWillAppear:(BOOL)animated {
    
    NSLog(@"First View will appear");
    [countryCode setText:country.code];
    [countryName setText:country.name];
    
}

//delegate function implemented
//this gets called from the second viewconroller when the view disappears
- (void) setScreenValues:(Country *)myCountry
{
    self.country = myCountry;
}


- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

Interface file for Second View Controller - SecondViewController.h

#import <UIKit/UIKit.h>
#import "Country.h"


//create this protocol so that we can pass information back
@protocol PassInformation <NSObject>

@optional

-(void) setScreenValues:(Country *)myCountry;

@end

@interface SecondViewController : UIViewController

@property Country *country;

@property UITextField *countryCode;
@property UITextField *countryName;

//define the delegate property
@property (nonatomic, unsafe_unretained) id<PassInformation> delegate;

@end

Implementation file for Second View Controller - SecondViewController.m

#import "SecondViewController.h"

@interface SecondViewController ()

@end

@implementation SecondViewController

@synthesize countryCode,countryName;
@synthesize country;
@synthesize delegate;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
        country = [[Country alloc] init];

    }
    return self;
}


- (void)viewDidLoad
{
    [super viewDidLoad];
    NSLog(@"Second view did load");
 // Do any additional setup after loading the view.
    
    [self.navigationItem setTitle:@"Second View"];
    
    [self.view setBackgroundColor:[UIColor lightGrayColor]];
    
    countryCode = [[UITextField alloc] init];
    [countryCode setBorderStyle: UITextBorderStyleRoundedRect];
    [countryCode setFrame:CGRectMake(10.0,10.0,200.0,30.0)];
    [countryCode setPlaceholder:@"Enter Country Code here"];
    [self.view addSubview: countryCode];
    
    countryName = [[UITextField alloc] init];
    [countryName setBorderStyle: UITextBorderStyleRoundedRect];
    [countryName setFrame:CGRectMake(10.0,50.0,200.0,30.0)];
    [countryName setPlaceholder:@"Enter Country Name here"];
    [self.view addSubview: countryName];
    

}

- (void) viewWillAppear:(BOOL)animated {
    
    NSLog(@"Second View will appear");
    [countryCode setText:country.code];
    [countryName setText:country.name];


}


- (void) viewWillDisappear:(BOOL) animated {
    
    NSLog(@"Second View will disappear");
    country.code = countryCode.text;
    country.name = countryName.text;
    
    //Is anyone listening
    if([[self delegate] respondsToSelector:@selector(setScreenValues:)])
    {
        //send the delegate function with the country information
        [[self delegate] setScreenValues:country];
    }
    
}


- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end