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