Passing Data between View Controllers

A ViewController in an application is seldom standalone in nature. They require data from ViewControllers in front and from those behind them, this leaves us with two types of data passing

  • Forward Data passing
  • Backward data passing

For discussing both kinds of data passing we have two ViewCotrollers

  • ASViewController
  • ASViewControllerB

Forward data passing between ViewControllers

Forward data passing can be done in two simple ways

  • Through Property in forward class :- Make a property in forward class ASViewControllerB and name it
    //Swift
    var valueToPass: String?
    
    // Objective-C   
    
    @property(nonatomic,assign)NSString* valueToPass;
    
    
    

    Now we can set the property we have made before pushing the object of ASViewControllerB in our navigation stack

    // Swift
      //create view controller of ASViewControllerB
            
            let viewControllerB = ASViewControllerB(nibName: "ASViewControllerB", bundle: nil);
            //set property/variable
            viewControllerB.valueToPass = "This will go to ASViewControllerB"
            //push in navigation stack
            self.navigationController?.pushViewController(viewControllerB, animated: true);
    
    
    //Objective-C
     //create view controller of ASViewControllerB
        ASViewControllerB *viewControllerB = [[ASViewControllerB alloc] initWithNibName:@"ASViewControllerB" bundle:nil];
        //set property/variable
        viewControllerB.valueToPass = @"This will go to ASViewControllerB";
        //push in navigation stack
         [self.navigationController pushViewController:viewControllerB animated:YES];
    
    
  • Through Segues  :- This method is very similar to the first one. We need to create property in same way.After that we need to create segue from ASViewController to ASViewControllerB and give it a identifier “datatopass”
    segue
    Passing Data between View Controllers

    Now we have a segue which we can identify and use it to get the reference of view controller and set its property.
    We nee to add method “prepareForSegue” in ASViewCotroller  which is called when a segue is performed. Inside this we get the segue object and we can check the identifier of segue object if it matches our identifier“datatopass” we will then get our forward ViewController from segues’s destinationViewController property and set our property “valueToPass

    //Swift
      override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
            
            if(segue.identifier == "datatopass")
            {
                let viewControllerB: ASViewControllerB = segue.destination as! ASViewControllerB
                
                viewControllerB.valueToPass = "This will go to ASViewControllerB"
            }
        }
    
    //Objective-C
    -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
        if([segue.destinationViewController  isEqual:  @"datatopass"])
        {
            ASViewControllerB *viewController =  segue.destinationViewController;
            viewController.valueToPass = @"This will go to ASViewControllerB";
            
        }
        
    }
    

    It could happen that your ViewController are embedded in navigation controller then you need to alter the above implementation a bit. First we will get UINavigationController object from identified segue and then we will fetch its top viewcontroller.

    //Swift
     override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
            
            if(segue.identifier == "datatopass")
            {
                let nav = segue.destination as! UINavigationController
                let viewControllerB: ASViewControllerB = nav.topViewController as! ASViewControllerB
                
                viewControllerB.valueToPass = "This will go to ASViewControllerB"
            }
        }
    //Objective-C
    -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
        if([segue.destinationViewController  isEqual:  @"datatopass"])
        {
            UINavigationController *nav = segue.destinationViewController;
            ASViewControllerB *viewController = (ASViewControllerB*)[nav topViewController];
            viewController.valueToPass = @"This will go to ASViewControllerB";
            
        }
        
    }
    

     

Backwards Data Passing Between ViewControllers

Backward data passing between ViewControllers can be done using many ways

  • Delegates
  • Blocks
  • Notifications

We will discuss Delegates as of now in this post

Delegates/Delegation is the process in which a class delegates some of its work to other class. For this method our class ASViewController will have to conform as Delegate of ASViewControllerB and implement its delegate method. Class ASViewControllerB will call the delegate with required parameters which will be passed to class ASViewController for necessary action. We will achieve this in multiple steps follow on

  1. Create a protocol in ASViewControllerB and call it ASViewControllerBDelegate. In objective-c do it in header file below #import and above @interface
    //Swift
    
    protocol ASViewControllerBDelegate {
        func dataToPass(data:String)
    }
    
    
    //Objective-C
    
    #import <UIKit/UIKit.h>
    
    @protocol ASViewControllerBDelegate <NSObject>
    
    -(void)dataToPass:(NSString*)data;
    
    @end
    

    As you can see protocol hold the function declaration.

  2. Now create a property named “delegate” In ASViewControllerB.
    //Swift
    
      var delegate: ASViewControllerBDelegate?
    
    //Objective-C
    
    @interface ASViewControllerB : UIViewController
    
    @property (nonatomic,assign)id <ASViewControllerBDelegate> delegate;
    

     

  3. In ASViewController we need to do few changes first we need to make it conform to ASViewControllerBDelegate for that we need to make addition in class header file in Objective-C and in class file in Swift
    //Swift
    //added ASViewControllerBDelegate in the begining of class
    class ASViewController: UIViewController,ASViewControllerBDelegate {//rest of class code
    
    
    
    //Objective-C
    @interface ASViewController : UIViewController<ASViewControllerBDelegate>
    
    @end
    

     

  4. Now since our class ASViewController has accepted the delegation of task declared in protocol ASViewControllerBDelegate it is bound to implement all function which are required and it can choose between optional functions. So after implementing function dataToPass in our class ASViewController
    //Swift
    
     func dataToPass(data: String) {
            print(data)
        }
    //Objective-C
    
    -(void)dataToPass:(NSString*)data{
        
        NSLog(@"%@",data);
    }

    We also need to set the delegate property we made in ASViewControllerB to self, before pushing it as we did in forward data passing between ViewControllers.

    //Swift
    
    //create view controller of ASViewControllerB
            
            let viewControllerB = ASViewControllerB(nibName: "ASViewControllerB", bundle: nil);
            //set property/variable
            viewControllerB.valueToPass = "This will go to ASViewControllerB"
            
            //set delegate
            viewControllerB.delegate = self;
            
            //push in navigation stack
            self.navigationController?.pushViewController(viewControllerB, animated: true);
    
    //Objective-C
     //create view controller of ASViewControllerB
        ASViewControllerB *viewControllerB = [[ASViewControllerB alloc] initWithNibName:@"ASViewControllerB" bundle:nil];
        
        //set property/variable
        
        viewControllerB.valueToPass = @"This will go to ASViewControllerB";
        
        //Set delegate
        viewControllerB.delegate =  self;
        //push in navigation stack
        
        [self.navigationController pushViewController:viewControllerB animated:YES];
    
    
    

     

  5.  Now we can call the method/function dataToPass from ASViewControllerB with our data and it will be received in implementation of dataToPass method/function in ASViewController
    //Swift
    
     if (self.delegate != nil){
                delegate?.dataToPass(data: "This will go back to ASViewController")
            }
    //Objective-C
    
      if([self.delegate respondsToSelector:@selector(dataToPass:)])
        {
            [self.delegate dataToPass:@"This will go back to ASViewController"];
        }
    

    You have successfully passed data between ViewControllers you are awesome

A pat on the back !!