Delegation Pattern in Objective-C
It's been a long time since I had to work with old good Objective-C, the king of brackets [[[[]]]]]]]. I recently had to revisit implementation of one of the fundamental design pattern in iOS, called Delegation.
According to Apple's documentation:
"Delegation is a simple and powerful pattern in which one object in a program acts on behalf of, or in coordination with, another object. The delegating object keeps a reference to the other object—the delegate—and at the appropriate time sends a message to it. The message informs the delegate of an event that the delegating object is about to handle or has just handled."
So how can it be implemented in Objective-C?
In this example:
- AppDelegate class is acting as receiver of delegated events
- TapProtocol defines the methods that have to be implemented by classes that are conforming to the protocol
- ViewController receives events from the button and passes it to delegate.
TapProtocol.h
#import <Foundation/Foundation.h>
@protocol TapProtocol <NSObject>
-(void) buttonTapped;
@end
AppDelegate.h
Notice how we it's specified that this class conforms to the TapProtocol:
@interface AppDelegate : UIResponder <UIApplicationDelegate, TapProtocol>
#import <UIKit/UIKit.h>
#import "TapProtocol.h"
@interface AppDelegate : UIResponder <UIApplicationDelegate, TapProtocol>
@property (strong, nonatomic) UIWindow *window;
@end
AppDelegate.m:
Code below indicates that we want AppDelegate to act as a delegate of ViewController's tap delegate protocol. In other words events from ViewController will be passed to this class. In order for this to happen you have to implement the methods specified by protocol:
- (void)buttonTapped{
NSLog(@"Button Tapped Here");
}
ViewController * vc = (ViewController *)[[[[UIApplication sharedApplication] delegate]window] rootViewController];
vc.delegate = self;
#import "AppDelegate.h"
#import "ViewController.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
ViewController * vc = (ViewController *)[[[[UIApplication sharedApplication] delegate]window] rootViewController];
vc.delegate = self;
return YES;
}
#pragma mark Delegate methods
- (void)buttonTapped{
NSLog(@"Button Tapped Here");
}
@end
Finally in ViewController you have to implement following code.
The crucial statements are:
@property (weak, nonatomic) id<TapProtocol> delegate;
declaring delegate.
[self.delegate buttonTapped];
Sending messages to delegate.
ViewController.h
#import <UIKit/UIKit.h>
@protocol TapProtocol;
@interface ViewController : UIViewController
@property (weak, nonatomic) id<TapProtocol> delegate;
@end
ViewController.m
#import "ViewController.h"
#import "TapProtocol.h"
@interface ViewController ()
@end
@implementation ViewController
- (IBAction)tapTap:(id)sender {
[self.delegate buttonTapped];
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (IBAction)buttonTapped:(id)sender {
[self.delegate buttonTapped];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end