Disclaimer: this is the Swift version of how to create a delegate.
So, what are delegates? …in software development, there are general reusable solution architectures that help to solve commonly occurring problems within a given context, these “templates”, so to speak, are best known as design patterns.
Delegates are a design pattern that allows one object to send messages to another object when a specific event happens.
Imagine an object A calls an object B to perform an action. Once the action is complete, object A should know that B has completed the task and take necessary action, this can be achieved with the help of delegates!
You can see an app with two classes, ViewController A and ViewController B. B has two views that on tap changes the background color of the ViewController, nothing too complicated right? well now let’s think in an easy way to also change the background color of class A when the views on class B are tapped.
The problem is that this views are part of class B and have no idea about class A, so we need to find a way to communicate between this two classes, and that’s where delegation shines.
I divided the implementation into 6 steps so you can use this as a cheat sheet when you need it.
step 1: Look for the pragma mark step 1 in ClassBVC file and add this
The first step is to create a protocol, in this case, we will create the protocol in class B, inside the protocol you can create as many functions that you want based on the requirements of your implementation. In this case, we just have one simple function that accepts an optional UIColor as an argument.
Is a good practice to name your protocols adding the word delegate at the end of the class name, in this case, ClassBVCDelegate.
step 2: Look for the pragma mark step 2 in ClassVBC and add this
//MARK: step 2 Create a delegate property here.
weak var delegate: ClassBVCDelegate?
Here we just create a delegate property for the class, this property must adopt the protocol type, and it should be optional. Also, you should add the weak keyword before the property to avoid retain cycles and potential memory leaks, if you don’t know what that means don’t worry for now, just remember to add this keyword.
step 3: Look for the pragma mark step 3 inside the handleTap method in ClassBVC and add this
//MARK: step 3 Add the delegate method call here.
delegate?.changeBackgroundColor(tapGesture.view?.backgroundColor)
One thing that you should know, run the app and tap on any view, you won’t see any new behavior and that’s correct but the thing that I want to point out is that the app it’s not crashing when the delegate is called, and it’s because we create it as an optional value and that’s why it won’t crash even the delegated doesn’t exist yet. Let’s now go to ClassAVC file and make it, the delegated.
step 4: Look for the pragma mark step 4 inside the handleTap method in ClassAVC and add this next to your class type like this.
//MARK: step 4 conform the protocol here.
class ClassAVC: UIViewController, ClassBVCDelegate {
}
Now ClassAVC adopted the ClassBVCDelegate protocol, you can see that your compiler is giving you an error that says “Type ‘ClassAVC does not conform to protocol ‘ClassBVCDelegate’ and this only means that you didn’t use the methods of the protocol yet, imagine that when class A adopts the protocol is like signing a contract with class B and this contract says “Any class adopting me MUST use my functions!”
Quick note: If you come from an Objective-C background you are probably thinking that you can also shut up that error making that method optional, but for my surprise, and probably yours, Swift language does not support optional protocols, if you want to do it you can create an extension for your protocol or use the @objc keyword in your protocol implementation.
Personally, If I have to create a protocol with different optional methods I would prefer to break it into different protocols, that way I will follow the concept of giving one single responsibility to my objects, but it can vary based on the specific implementation.
step 5: Look for the pragma mark step 5 inside the prepare for segue method and add this
//MARK: step 5 create a reference of Class B and bind them through the `prepareforsegue` method.
if let nav = segue.destination as? UINavigationController, let classBVC = nav.topViewController as? ClassBVC {
classBVC.delegate = self
}
Here we are just creating an instance of ClassBVC and assign its delegate to self, but what is self here? well, self is the ClassAVC which has been delegated!
step 6: Finally, look for the pragma step 6 in ClassAVC and let’s use the functions of the protocol, start typing func changeBackgroundColor and you will see that it’s auto-completing it for you. You can add any implementation inside it, in this example, we will just change the background color, add this.
//MARK: step 6 finally use the method of the contract
func changeBackgroundColor(_ color: UIColor?) {
view.backgroundColor = color
}
Now run the app!
Delegates are everywhere and you probably use them without even notice, if you create a tableview in the past you used delegation, many classes of UIKIT works around them and many other frameworks too, they solve these main problems.
Avoid tight coupling of objects.
Modify behavior and appearance without the need to subclass objects.
Allow tasks to be handled off to any arbitrary object.
Congratulations, you just implement a custom delegate, I know that you are probably thinking, so much trouble just for this? well, delegation is a very important design pattern to understand if you want to become an iOS developer, and always keep in mind that they have one to one relationship between objects.
When using the formal protocol method for creating delegate support, I've found that you can ensure proper type checking (albeit, runtime, not compile time) by adding something like:
if (![delegate conformsToProtocol:@protocol(MyDelegate)]) {
[NSException raise:@"MyDelegate Exception"
format:@"Parameter does not conform to MyDelegate protocol at line %d", (int)__LINE__];
}
in your delegate accessor (setDelegate) code. This helps minimize mistakes.
Create Protocol in .h file. Make sure that is defined before the protocol using @class followed by the name of the UIViewController < As the protocol I am going to use is UIViewController class>.
Step : 1 : Create a new class Protocol named "YourViewController" which will be the subclass of UIViewController class and assign this class to the second ViewController.
Step : 2 : Go to the "YourViewController" file and modify it as below:
#import <UIKit/UIkit.h>
@class YourViewController;
@protocol YourViewController Delegate <NSObject>
@optional
-(void)defineDelegateMethodName: (YourViewController *) controller;
@required
-(BOOL)delegateMethodReturningBool: (YourViewController *) controller;
@end
@interface YourViewController : UIViewController
//Since the property for the protocol could be of any class, then it will be marked as a type of id.
@property (nonatomic, weak) id< YourViewController Delegate> delegate;
@end
The methods defined in the protocol behavior can be controlled with @optional and @required as part of the protocol definition.
Step : 3 :Implementation of Delegate
#import "delegate.h"
@interface YourDelegateUser ()
<YourViewControllerDelegate>
@end
@implementation YourDelegateUser
- (void) variousFoo {
YourViewController *controller = [[YourViewController alloc] init];
controller.delegate = self;
}
-(void)defineDelegateMethodName: (YourViewController *) controller {
// handle the delegate being called here
}
-(BOOL)delegateMethodReturningBool: (YourViewController *) controller {
// handle the delegate being called here
return YES;
}
@end
//test whether the method has been defined before you call it
An Objective-C delegate is an object that has been assigned to the delegate property another object. To create one, you simply define a class that implements the delegate methods you're interested in, and mark that class as implementing the delegate protocol.
For example, suppose you have an UIWebView. If you'd like to implement its delegate's webViewDidStartLoad: method, you could create a class like this:
On the UIWebView side, it probably has code similar to this to see if the delegate responds to the webViewDidStartLoad: message using respondsToSelector: and send it if appropriate.
The delegate property itself is typically declared weak (in ARC) or assign (pre-ARC) to avoid retain loops, since the delegate of an object often holds a strong reference to that object. (For example, a view controller is often the delegate of a view it contains.)
Making Delegates for Your Classes
To define your own delegates, you'll have to declare their methods somewhere, as discussed in the Apple Docs on protocols. You usually declare a formal protocol. The declaration, paraphrased from UIWebView.h, would look like this:
@protocol UIWebViewDelegate <NSObject>
@optional
- (void)webViewDidStartLoad:(UIWebView *)webView;
// ... other methods here
@end
This is analogous to an interface or abstract base class, as it creates a special type for your delegate, UIWebViewDelegate in this case. Delegate implementors would have to adopt this protocol:
And then implement the methods in the protocol. For methods declared in the protocol as @optional (like most delegate methods), you need to check with -respondsToSelector: before calling a particular method on it.
Naming
Delegate methods are typically named starting with the delegating class name, and take the delegating object as the first parameter. They also often use a will-, should-, or did- form. So, webViewDidStartLoad: (first parameter is the web view) rather than loadStarted (taking no parameters) for example.
Speed Optimizations
Instead of checking whether a delegate responds to a selector every time we want to message it, you can cache that information when delegates are set. One very clean way to do this is to use a bitfield, as follows:
Then, in the body, we can check that our delegate handles messages by accessing our delegateRespondsTo struct, rather than by sending -respondsToSelector: over and over again.
Informal Delegates
Before protocols existed, it was common to use a category on NSObject to declare the methods a delegate could implement. For example, CALayer still does this:
@interface NSObject(CALayerDelegate)
- (void)displayLayer:(CALayer *)layer;
// ... other methods here
@end
This essentially tells the compiler that any object might implement displayLayer:.
You would then use the same -respondsToSelector: approach as described above to call this method. Delegates simply implement this method and assign the delegate property, and that's it (there's no declaring you conform to a protocol). This method is common in Apple's libraries, but new code should use the more modern protocol approach above, since this approach pollutes NSObject (which makes autocomplete less useful) and makes it hard for the compiler to warn you about typos and similar errors.
Disclaimer: this is the
Swift
version of how to create adelegate
.So, what are delegates? …in software development, there are general reusable solution architectures that help to solve commonly occurring problems within a given context, these “templates”, so to speak, are best known as design patterns. Delegates are a design pattern that allows one object to send messages to another object when a specific event happens. Imagine an object A calls an object B to perform an action. Once the action is complete, object A should know that B has completed the task and take necessary action, this can be achieved with the help of delegates!
For a better explanation, I am going to show you how to create a custom delegate that passes data between classes, with Swift in a simple application,start by downloading or cloning this starter project and run it!
You can see an app with two classes,
ViewController A
andViewController B
. B has two views that on tap changes the background color of theViewController
, nothing too complicated right? well now let’s think in an easy way to also change the background color of class A when the views on class B are tapped.The problem is that this views are part of class B and have no idea about class A, so we need to find a way to communicate between this two classes, and that’s where delegation shines. I divided the implementation into 6 steps so you can use this as a cheat sheet when you need it.
step 1: Look for the pragma mark step 1 in ClassBVC file and add this
The first step is to create a
protocol
, in this case, we will create the protocol in class B, inside the protocol you can create as many functions that you want based on the requirements of your implementation. In this case, we just have one simple function that accepts an optionalUIColor
as an argument. Is a good practice to name your protocols adding the worddelegate
at the end of the class name, in this case,ClassBVCDelegate
.step 2: Look for the pragma mark step 2 in
ClassVBC
and add thisHere we just create a delegate property for the class, this property must adopt the
protocol
type, and it should be optional. Also, you should add the weak keyword before the property to avoid retain cycles and potential memory leaks, if you don’t know what that means don’t worry for now, just remember to add this keyword.step 3: Look for the pragma mark step 3 inside the handleTap
method
inClassBVC
and add thisOne thing that you should know, run the app and tap on any view, you won’t see any new behavior and that’s correct but the thing that I want to point out is that the app it’s not crashing when the delegate is called, and it’s because we create it as an optional value and that’s why it won’t crash even the delegated doesn’t exist yet. Let’s now go to
ClassAVC
file and make it, the delegated.step 4: Look for the pragma mark step 4 inside the handleTap method in
ClassAVC
and add this next to your class type like this.Now ClassAVC adopted the
ClassBVCDelegate
protocol, you can see that your compiler is giving you an error that says “Type ‘ClassAVC does not conform to protocol ‘ClassBVCDelegate’ and this only means that you didn’t use the methods of the protocol yet, imagine that when class A adopts the protocol is like signing a contract with class B and this contract says “Any class adopting me MUST use my functions!”Quick note: If you come from an
Objective-C
background you are probably thinking that you can also shut up that error making that method optional, but for my surprise, and probably yours,Swift
language does not support optionalprotocols
, if you want to do it you can create an extension for yourprotocol
or use the @objc keyword in yourprotocol
implementation.Personally, If I have to create a protocol with different optional methods I would prefer to break it into different
protocols
, that way I will follow the concept of giving one single responsibility to my objects, but it can vary based on the specific implementation.here is a good article about optional methods.
step 5: Look for the pragma mark step 5 inside the prepare for segue method and add this
Here we are just creating an instance of
ClassBVC
and assign its delegate to self, but what is self here? well, self is theClassAVC
which has been delegated!step 6: Finally, look for the pragma step 6 in
ClassAVC
and let’s use the functions of theprotocol
, start typing func changeBackgroundColor and you will see that it’s auto-completing it for you. You can add any implementation inside it, in this example, we will just change the background color, add this.Now run the app!
Delegates
are everywhere and you probably use them without even notice, if you create atableview
in the past you used delegation, many classes ofUIKIT
works around them and many otherframeworks
too, they solve these main problems.Congratulations, you just implement a custom delegate, I know that you are probably thinking, so much trouble just for this? well, delegation is a very important design pattern to understand if you want to become an
iOS
developer, and always keep in mind that they have one to one relationship between objects.You can see the original tutorial here
When using the formal protocol method for creating delegate support, I've found that you can ensure proper type checking (albeit, runtime, not compile time) by adding something like:
in your delegate accessor (setDelegate) code. This helps minimize mistakes.
Here is a simple method to create delegates
Create Protocol in .h file. Make sure that is defined before the protocol using @class followed by the name of the UIViewController
< As the protocol I am going to use is UIViewController class>.
Step : 1 : Create a new class Protocol named "YourViewController" which will be the subclass of UIViewController class and assign this class to the second ViewController.
Step : 2 : Go to the "YourViewController" file and modify it as below:
The methods defined in the protocol behavior can be controlled with @optional and @required as part of the protocol definition.
Step : 3 : Implementation of Delegate
//test whether the method has been defined before you call it
Answer is actually answered, but I would like to give you a "cheat sheet" for creating a delegate:
An Objective-C delegate is an object that has been assigned to the
delegate
property another object. To create one, you simply define a class that implements the delegate methods you're interested in, and mark that class as implementing the delegate protocol.For example, suppose you have an
UIWebView
. If you'd like to implement its delegate'swebViewDidStartLoad:
method, you could create a class like this:Then you could create an instance of MyClass and assign it as the web view's delegate:
On the
UIWebView
side, it probably has code similar to this to see if the delegate responds to thewebViewDidStartLoad:
message usingrespondsToSelector:
and send it if appropriate.The delegate property itself is typically declared
weak
(in ARC) orassign
(pre-ARC) to avoid retain loops, since the delegate of an object often holds a strong reference to that object. (For example, a view controller is often the delegate of a view it contains.)Making Delegates for Your Classes
To define your own delegates, you'll have to declare their methods somewhere, as discussed in the Apple Docs on protocols. You usually declare a formal protocol. The declaration, paraphrased from UIWebView.h, would look like this:
This is analogous to an interface or abstract base class, as it creates a special type for your delegate,
UIWebViewDelegate
in this case. Delegate implementors would have to adopt this protocol:And then implement the methods in the protocol. For methods declared in the protocol as
@optional
(like most delegate methods), you need to check with-respondsToSelector:
before calling a particular method on it.Naming
Delegate methods are typically named starting with the delegating class name, and take the delegating object as the first parameter. They also often use a will-, should-, or did- form. So,
webViewDidStartLoad:
(first parameter is the web view) rather thanloadStarted
(taking no parameters) for example.Speed Optimizations
Instead of checking whether a delegate responds to a selector every time we want to message it, you can cache that information when delegates are set. One very clean way to do this is to use a bitfield, as follows:
Then, in the body, we can check that our delegate handles messages by accessing our
delegateRespondsTo
struct, rather than by sending-respondsToSelector:
over and over again.Informal Delegates
Before protocols existed, it was common to use a category on
NSObject
to declare the methods a delegate could implement. For example,CALayer
still does this:This essentially tells the compiler that any object might implement
displayLayer:
.You would then use the same
-respondsToSelector:
approach as described above to call this method. Delegates simply implement this method and assign thedelegate
property, and that's it (there's no declaring you conform to a protocol). This method is common in Apple's libraries, but new code should use the more modern protocol approach above, since this approach pollutesNSObject
(which makes autocomplete less useful) and makes it hard for the compiler to warn you about typos and similar errors.Please! check below simple step by step tutorial to understand how Delegates works in iOS.
I have created two ViewControllers (for sending data from one to another)