Using Delegate and Protocol is an essential design pattern in iOS, used to pass data between View Controllers and orchestrate workflows in iOS. For instance, when calling a URL Connection module, the input variables to make a JSON REST request and the output response data are passed by properties using a callback method defined by the URL Connection module’s protocol. In order to know which class to callback, the calling class sets itself as the delegate property of the URL Connection module, and is then called back via a method it must implement, following the Protocol’s signature.
The basic design consists of a calling class A.class and a called class B.class:
1. Define a Protocol in B with a callback method, e.g. named -(void)returnFromB:(B *)controller.
2. Define a delegate property in B, e.g. @property id returnFromBDelegate.
3. A must implement the callback method that Protocol B prescribes, so add the <BProtocol> and a method -(void)returnFromB:(B *)controller.
4. A calls a workers method in B, and sets itself as the delegate of B.
5. When workers method is done, B calls A back by calling the callback method on its delegate, which is A.
// A.h
#import <UIKit/UIKit.h>
#import "B.h"
@interface A : UIViewController <BProtocol>
@end
// A.m
#import "B.h"
@interface A()
@end
@implementation A
// call B programmatically or use a segue
-(void)callB
{
UIStoryboard *BStoryBoard = [UIStoryboard storyboardWithName:@"BStoryboard" bundle:[NSBundle mainBundle]];
B *b = [BStoryBoard instantiateInitialViewController];
b.returnFromBDelegate = self;
[self presentViewController:b animated:YES completion:^{}];
}
// callback method for B as prescribed by BProtocol
- (void)returnFromB:(B *)controller
{
// for instance dismiss the B controller scene here
[controller dismissViewControllerAnimated:YES completion:^{}];
}
@end
// B.h
#import <UIKit/UIKit.h>
@class B;
@protocol BProtocol
- (void)returnFromB:(B *)controller;
@end
@interface B : UIViewController
@property id returnFromBDelegate;
- (IBAction)backButtonPressed:(id)sender;
@end
// B.m
@interface B ()
@end
@implementation B
@synthesize returnFromBDelegate;
-(IBAction)backButtonPressed:(id)sender
{
[self.returnFromBDelegate returnFromB:self];
}
@end