Brittany Graft, 6 months ago
Are you new to delegation in Swift? Let’s talk about two great ways to start using delegates and protocols in your code. But first, what are delegates? Delegation is a design pattern that allows one object to communicate with another object when a specific event occurs. The delegating object keeps a reference to the other object (the delegate) and sends a message to it at the appropriate time. This allows us to update the delegate to reflect the completion of the event. Great!
So, let’s talk about the easiest places to start implementing custom delegates.
To create a pop-up window, add a new CocoaTouch View Controller class to your project file and select the box that says “Also create XIB file”. This is where we will build our pop-up view. Let’s name it “PopUpViewController”. This will be our delegating object. In your .xib file, add two buttons. Link up outlets to your PopUpViewController.swift file. We will name the first button “optionAButton” and the second button “optionBButton”. The goal here is, from your presenting view controller, to detect which option the user selects. Let’s refer to your presenting view controller as “MainViewController”. We will also refer to this view controller as our delegate. We will need to communicate between the two classes - and this is where delegation is very helpful!
The first step is to create a protocol. What’s a protocol? A protocol defines a set of functions, properties or other requirements to accomplish a particular task. A protocol can be adopted by a class, struct or enum that, in turn, will provide the implementation of those requirements, and which is said to conform to that protocol. So basically, the protocol defines the responsibilities that will be delegated.
So, back to our code. Lets add a protocol named “PopUpDelegate” to the top of our PopUpViewController.swift file. We will add two functions (think “responsibilities”) to our protocol that our delegate will later implement. It will look like this:
You may notice, that we also added the delegate property on our PopUpViewController. This is so it can be accessible through our MainViewController. You will see, later on, the MainViewController will assign the PopUpViewController’s delegate to itself.
Next, let’s wire up IBActions for our two buttons.
The important thing to remember here is that the IBAction detects the user interaction with PopUpViewController. Once we are inside of that function, we are letting the delegate know that we are calling the delegate method.
Now, let’s turn back to our MainViewController and implement our delegate methods. (As a reminder, these methods are defined in our PopUpDelegate Protocol and called in our PopUpViewController. Now, its time to decide what to do now that they have been called!)
Firstly, our MainViewController needs to conform to the PopUpDelegate protocol. With the addition of the protocol after the class definition, your compiler should be giving you an error that says that the MainViewController class does not conform to the PopUpDelegate protocol. So, let’s fix that! We will add the two functions listed in the PopUpDelegate protocol. For now, we will just print out that the specific button was pressed.
We still don’t have any way of seeing our PopUpViewController though. So let’s define the PopUpViewController class in our MainViewController and push the pop up. We are going to add a button on the MainViewController that the user can push to show the pop up. And then, let’s not forget the important step of assigning the PopUpViewController’s delegate to MainViewController!
After implementing this code, you should get an error message that PopUpViewController has no member “showInView”. Let’s switch back to our PopUpViewController and add that function. We will also add the showAnimate() and removeAnimate() functions with some custom animations for our pop up.
After running your project, upon clicking Button A or Button B, you should see the corresponding statement printed out in your log and the pop up window should close. And that’s it! You have now successfully implemented your first custom delegate. Congratulations! As a challenge, see if you can pass text in a text field back to your presenting view controller. If you would like to see the project source code, please visit here: https://github.com/brittanygraft/DelegatesAndProtocolsTutorial
2) Detecting Button Press in Custom Tableview Cell
Since you are already a pro at delegates and protocols, we won’t go into as much detail on this example, but will instead use the terms we defined in the previous example.
Create a custom tableview cell; this will be our delegating object. Let’s name it CustomTableViewCell. Add one label and two buttons in the tableview cell .xib file, title the buttons “Call” and “Email” and hook them up to your .swift file as IBOutlets and IBActions.
Create a protocol above this class; we will name it ActionButtonDelegate. Inside the protocol, add two functions: callButtonWasPressed(button: UIButton) and emailButtonWasPressed(button: UIButton).
Add the delegate property to your CustomTableViewCell class:
var delegate: ActionButtonDelegate?
Also in the CustomTableViewCell class, inside your IBAction functions for each of your two buttons, call the corresponding delegate method:
(the “button” here is the sender. It is passed in in the IBAction function)
So, now, we will flip over to the class where our tableview is defined. We will name this view controller “MainViewController”; this is our delegate. Make this delegate conform to the ActionButtonDelegate protocol and again you should get an error that it doesn’t yet.
First though, let’s create an array of dictionaries that will hold all of our tableview data. Let’s call it dataArray.
It will look something like this:
Now, in your tableview cellForRowAtIndexPath method, define your custom cell as you normally would and then add the following line:
cell.delegate = self
This will make the MainViewController the delegate for the custom cell.
Also in this method, let’s set the cell.callButton.tag to be equal to indexPath.row and the cell.emailButton.tag to be equal to indexPath.row, as well. It should look like this:
Now, we can implement our delegate methods.
Here, you will see that we added the button tag so that we can get the appropriate dictionary out of the dataArray. We add actions to our delegate methods and that’s it!