1 00:00:00,320 --> 00:00:03,600 Hi. My named is Amit,@paradoxed on Twitter. 2 00:00:03,600 --> 00:00:06,040 So today we're gonna talk about delegation. 3 00:00:06,040 --> 00:00:11,660 Delegation is a very common design pattern used all over when programming an iOS app. 4 00:00:11,660 --> 00:00:16,410 If you've done any of our courses like the Blog Reader project or the Ribbit 5 00:00:16,410 --> 00:00:18,570 app, you've noticed that within the table 6 00:00:18,570 --> 00:00:22,280 View Controller, you have the table view delegate. 7 00:00:22,280 --> 00:00:25,240 And then if you've used a scroll view or a text field, 8 00:00:25,240 --> 00:00:28,260 you've probably used a delegate to go along with that. 9 00:00:28,260 --> 00:00:30,620 So we've used delegate all over the places but we've 10 00:00:30,620 --> 00:00:35,970 never specifically addressed what is the delegate, a design pattern. 11 00:00:35,970 --> 00:00:40,560 Now a delegate or a protocol is basically something that defines 12 00:00:40,560 --> 00:00:44,370 a bunch of methods that can be implemented by any class. 13 00:00:44,370 --> 00:00:50,120 It's the most common design pattern and it means, to delegate control. 14 00:00:50,120 --> 00:00:50,510 So you 15 00:00:50,510 --> 00:00:53,250 are basically giving over control and having 16 00:00:53,250 --> 00:00:57,720 that class implement the functionality of that method. 17 00:00:57,720 --> 00:00:59,420 So let's take a look at how you can 18 00:00:59,420 --> 00:01:03,260 define a protocol, and then implement that in a class. 19 00:01:04,770 --> 00:01:06,900 Alright, I've created a sample app over 20 00:01:06,900 --> 00:01:11,450 here, and, basically it's a single view application. 21 00:01:11,450 --> 00:01:13,330 Let me run the app. 22 00:01:13,330 --> 00:01:16,036 And what you'll see is that there's a button here. 23 00:01:16,036 --> 00:01:21,320 Which says, press me, and then a text is displayed on the text label. 24 00:01:22,640 --> 00:01:27,550 So the way this app is designed is that if I go to the main story board you won't see 25 00:01:27,550 --> 00:01:31,310 anything because it's just a simple view, so there is 26 00:01:31,310 --> 00:01:34,310 our view controller and it has the main view in it. 27 00:01:35,500 --> 00:01:41,090 And let me go to the ViewController.m and you'll see that 28 00:01:41,090 --> 00:01:45,510 it has a property called THCustomView and 29 00:01:46,700 --> 00:01:51,030 all I do is add this custom view as a sub view to my 30 00:01:51,030 --> 00:01:55,620 main view. Now this custom view, let's head on over 31 00:01:55,620 --> 00:02:01,140 to customview.h, as you can see the interface, all it has 32 00:02:01,140 --> 00:02:06,398 is a method called set text where you can set the text of the 33 00:02:06,398 --> 00:02:09,080 label in the custom view. 34 00:02:10,130 --> 00:02:14,510 Now, the, this is assuming that you have created this custom view 35 00:02:14,510 --> 00:02:19,320 that you want to reuse it in multiple places throughout your application. 36 00:02:19,320 --> 00:02:23,810 And you do not want to give direct access to the button or the label. 37 00:02:23,810 --> 00:02:27,470 You just want the person using the custom view to set the 38 00:02:27,470 --> 00:02:31,960 text and then you want to control the look and feel and 39 00:02:31,960 --> 00:02:37,020 the color and all the other attributes of the controls that are housed 40 00:02:37,020 --> 00:02:42,040 within this custom view. Now of course, as a contrived example, 41 00:02:42,040 --> 00:02:47,180 I'm just trying to drive home the point that if you create a complex view 42 00:02:47,180 --> 00:02:52,370 that can be reused throughout your application or you're creating a third 43 00:02:52,370 --> 00:02:57,430 party component so that other people can use it or opensource 44 00:02:57,430 --> 00:02:58,930 this component. 45 00:02:58,930 --> 00:03:03,940 And you don't want to give completely control over all the controls within that 46 00:03:03,940 --> 00:03:10,590 custom view, then what happens is that when a button is pressed. 47 00:03:10,590 --> 00:03:17,030 Now, it's assuming that you, you can, of course, expose the button press method 48 00:03:17,030 --> 00:03:22,680 and set target actions to other view controllers, but the way this custom 49 00:03:22,680 --> 00:03:27,590 control is designed is that you have a button press method with that, within the 50 00:03:27,590 --> 00:03:34,910 custom view, so it's setting itself a text when the button is pressed. 51 00:03:34,910 --> 00:03:40,102 Now, inside the THView controller.m, I actually 52 00:03:40,102 --> 00:03:44,750 want to receive that button pressed event. 53 00:03:44,750 --> 00:03:48,070 I want to know when that button was pressed within the custom 54 00:03:48,070 --> 00:03:52,500 view, so that I can go ahead and call that set text method. 55 00:03:52,500 --> 00:03:55,290 I can simply set the text, but that doesn't help me because 56 00:03:55,290 --> 00:04:00,500 I want to set the text only if the button has been pressed. 57 00:04:00,500 --> 00:04:02,580 Now how do, how does the custom view 58 00:04:02,580 --> 00:04:07,940 instruct the THviewController that the button was pressed. 59 00:04:07,940 --> 00:04:13,745 Right now there's no way of doing that unless we expose the button 60 00:04:13,745 --> 00:04:16,790 as a public property. Right now it's a private property. 61 00:04:16,790 --> 00:04:18,760 Both of these are private properties. 62 00:04:20,740 --> 00:04:22,920 But let's say you've created a, a custom 63 00:04:22,920 --> 00:04:25,240 view and you don't wanna expose these things 64 00:04:25,240 --> 00:04:28,140 as, public properties because you don't want them 65 00:04:28,140 --> 00:04:30,840 to manipulate the look and feel of your control. 66 00:04:32,300 --> 00:04:35,590 So, in the init frame, basically, we are setting the frame for the 67 00:04:35,590 --> 00:04:38,830 button and adding it as a sub-view and the same thing we're doing 68 00:04:38,830 --> 00:04:39,520 for the label. 69 00:04:41,270 --> 00:04:47,020 Now the only way we can do this is if we create a delegate object that 70 00:04:47,020 --> 00:04:52,660 delegates the responsibility of the button-press method to its delegate. 71 00:04:53,890 --> 00:04:58,930 So the only way we can do that is if we create a delegate object within our 72 00:04:58,930 --> 00:05:04,140 custom view that would delegate the responsibility of the button 73 00:05:04,140 --> 00:05:07,830 press method to its delegate. So how do we go 74 00:05:07,830 --> 00:05:11,740 about doing that? Well let's take a look, so, the first 75 00:05:11,740 --> 00:05:15,380 thing I would need in my interface is a delegate object. 76 00:05:16,380 --> 00:05:22,670 So we'll say at property nonatomic, and this would be weak, this is the 77 00:05:22,670 --> 00:05:29,260 perfect example of using a weak property you will see that in a little 78 00:05:29,260 --> 00:05:33,110 bit why it's a weak property and not very strong. 79 00:05:33,110 --> 00:05:39,040 So, I have defined this delegate which is of type id. 80 00:05:39,040 --> 00:05:42,659 We, we don't specify exactly what this is, because we 81 00:05:42,659 --> 00:05:46,060 don't know what kind of delegate it's going to be. 82 00:05:46,060 --> 00:05:49,470 It could be a view controller, it could be another view, it 83 00:05:49,470 --> 00:05:53,460 could be a table view controller, it could be a scroll view. 84 00:05:53,460 --> 00:05:54,280 Anything could be a 85 00:05:54,280 --> 00:05:56,350 delegate of this custom view. 86 00:05:56,350 --> 00:06:01,200 We don't know what could be the delegate, that's why it's an id, which means that 87 00:06:01,200 --> 00:06:06,370 the type of this object is going to be determined at run time. 88 00:06:08,030 --> 00:06:11,950 So, the next thing we need to do is define a protocol. 89 00:06:11,950 --> 00:06:15,898 Now a protocol as its, as the name states, is, is 90 00:06:15,898 --> 00:06:21,060 a set of methods that can be implemented by a delegate. 91 00:06:21,060 --> 00:06:25,310 So the delegate needs some sort of structure, the 92 00:06:25,310 --> 00:06:27,980 delegate just can't be like, well I am going 93 00:06:27,980 --> 00:06:30,370 to do x, y and z, no, the delegate 94 00:06:30,370 --> 00:06:34,640 needs some set up instructions that it can implement. 95 00:06:34,640 --> 00:06:37,830 So we need to define what those instructions look like. 96 00:06:37,830 --> 00:06:40,420 So you need to declare the instructions, which is a 97 00:06:40,420 --> 00:06:45,250 protocol, and then that protocol is implemented by your delegate. 98 00:06:47,220 --> 00:06:53,470 So we will declare our protocol right here in our THCustomView. 99 00:06:53,470 --> 00:06:57,020 So it's after the interface implementation. 100 00:06:57,020 --> 00:07:00,522 So, as you can see, after the end, @end over here. 101 00:07:01,670 --> 00:07:06,770 So we need to give our protocol a name. So, the protocol names are basically the 102 00:07:06,770 --> 00:07:13,410 name of the class that needs a protocol followed by the suffix delegate. 103 00:07:13,410 --> 00:07:18,380 Now, it's usually a protocol on NSObject, so we'll leave that as is. 104 00:07:18,380 --> 00:07:20,420 And then we define our methods. 105 00:07:20,420 --> 00:07:24,070 Now similarly, as you define methods in your @interface, you 106 00:07:24,070 --> 00:07:28,670 can have class methods or you can have instance methods. 107 00:07:28,670 --> 00:07:33,580 So I'll create a instance method called buttonPressed. 108 00:07:35,960 --> 00:07:38,780 Now mind you, this can be called anything you want. 109 00:07:38,780 --> 00:07:40,920 I'm simply calling it buttonPressed because we're 110 00:07:40,920 --> 00:07:46,480 delegating that button pressed action to our delegate. 111 00:07:46,480 --> 00:07:49,600 Alright, so now that we've defined our protocol, it's always 112 00:07:49,600 --> 00:07:54,830 good practice to define what kind of delegate this is. 113 00:07:54,830 --> 00:07:57,900 So, as you can see in these angle brackets 114 00:07:57,900 --> 00:08:00,960 over here, you specified NSObject, which means that the 115 00:08:00,960 --> 00:08:07,770 protocol is of type NF, NSObject. Similarly, you can mention 116 00:08:07,770 --> 00:08:14,250 that this delegate should only be of type THView custom delegate. 117 00:08:16,120 --> 00:08:20,140 You don't want the other class just implementing any kind of delegate 118 00:08:20,140 --> 00:08:25,023 and hoping that this will work, cuz otherwise you'll get a run-time error. 119 00:08:25,023 --> 00:08:26,100 At least when you put 120 00:08:26,100 --> 00:08:33,990 this here, you will get a compiler warning if that delegate hasn't been specified. 121 00:08:33,990 --> 00:08:38,740 We'll come to it when we actually define the delegate in the view controller. 122 00:08:38,740 --> 00:08:42,090 So you'll get a better understanding of why I'm doing this. 123 00:08:42,090 --> 00:08:43,580 Now of course, we're getting an error 124 00:08:43,580 --> 00:08:47,090 here saying that, cannot find protocol declaration. 125 00:08:48,650 --> 00:08:51,512 That's because our protocol is defined after 126 00:08:51,512 --> 00:08:57,500 the@Interface, so one way we can prevent that 127 00:08:57,500 --> 00:09:02,530 error is just cause copying the @protocol ThCustomViewDelegate. 128 00:09:02,530 --> 00:09:06,740 Just as we define an @class, which is a forward declaration, that 129 00:09:06,740 --> 00:09:10,460 hey, this is a class that's going to be implemented in the future. 130 00:09:11,670 --> 00:09:16,630 Similarly we can specify a forward declaration for our protocol. 131 00:09:16,630 --> 00:09:20,380 So basically we're telling the compiler that this is a forward 132 00:09:20,380 --> 00:09:25,160 declaration for a protocol and we're gonna declare it later on somewhere. 133 00:09:25,160 --> 00:09:29,206 And later on, in this case, is right after our @interface declaration. 134 00:09:30,300 --> 00:09:35,840 So, here we have actually created our own, very own protocol. 135 00:09:35,840 --> 00:09:38,050 Now you've must have seen these protocols with 136 00:09:38,050 --> 00:09:41,545 table view controllers or scroll views or text fields. 137 00:09:41,545 --> 00:09:46,370 There are so many delicates defined for you in the UIKit framework. 138 00:09:46,370 --> 00:09:49,080 And here we are defining our very own delegate. 139 00:09:51,770 --> 00:09:55,890 So let's go ahead and see how we can implement this delegate. 140 00:09:55,890 --> 00:10:01,540 So, when we go back to our THViewController.m, and 141 00:10:01,540 --> 00:10:07,218 here in our self.customView, we can refer to that delegate property. 142 00:10:07,218 --> 00:10:14,338 So .customView.delegate 143 00:10:14,338 --> 00:10:17,370 and here we can just specify self. 144 00:10:17,370 --> 00:10:21,900 Because we're saying we are going to be the delegate for the custom view. 145 00:10:21,900 --> 00:10:25,390 We're gonna take over the responsibility of that button 146 00:10:25,390 --> 00:10:29,162 press method, or any other methods the protocol provides. 147 00:10:31,860 --> 00:10:37,260 So, as you can see here, I get a compiler warning and if I click here it says 148 00:10:37,260 --> 00:10:43,430 assigning id THCustomViewDelicate from incompatible type, so that's 149 00:10:43,430 --> 00:10:49,730 why we specify the THCustomViewDelegate in angle brackets. 150 00:10:49,730 --> 00:10:53,340 Because it's saying like, are you really haven't implemented this delegate. 151 00:10:53,340 --> 00:10:56,970 And by implementing, we have to go to the 152 00:10:56,970 --> 00:10:59,510 interface definition of our view controllers. 153 00:10:59,510 --> 00:11:01,370 So let's go to the .h file. 154 00:11:02,560 --> 00:11:07,230 And here is where we specify THCustomViewDelegate. 155 00:11:08,380 --> 00:11:14,430 So that's where we need to specify it and as you can see, we get an error saying 156 00:11:14,430 --> 00:11:21,895 that it cannot find the protocol. So let's Import our THCustomView. 157 00:11:23,470 --> 00:11:24,770 So that error will go away. 158 00:11:25,820 --> 00:11:28,160 And so now when we go back to 159 00:11:28,160 --> 00:11:32,820 our implementation, we don't get the error anymore. 160 00:11:32,820 --> 00:11:37,000 You know, it, it's satisfied that you're gonna be implementing this delegate. 161 00:11:37,000 --> 00:11:39,810 Now, we get another warning here, saying 162 00:11:39,810 --> 00:11:43,790 that method, buttonPressed in protocol not implemented. 163 00:11:45,020 --> 00:11:48,800 That's because we have to implement the methods required 164 00:11:48,800 --> 00:11:50,300 by our protocol. 165 00:11:52,480 --> 00:11:58,490 So, here we'll go and define the button press method. 166 00:12:01,260 --> 00:12:06,639 So we'll say self.customView set text. 167 00:12:08,370 --> 00:12:15,404 And let's set the text, we'll say button pressed 168 00:12:15,404 --> 00:12:20,510 view controller. 169 00:12:20,510 --> 00:12:21,420 So, are we done? 170 00:12:21,420 --> 00:12:26,190 Well, let's run our application and see if this works, 171 00:12:26,190 --> 00:12:30,040 and it won't work but let me show you anyway. 172 00:12:30,040 --> 00:12:32,690 So it says button pressed custom view, and 173 00:12:32,690 --> 00:12:36,430 it should really be saying, button pressed view controller. 174 00:12:36,430 --> 00:12:40,560 Let me remove this space here so that work's consistent. 175 00:12:41,680 --> 00:12:42,880 So why doesn't it work? 176 00:12:42,880 --> 00:12:47,580 We've set our delegates, we've set our button pressed methods. 177 00:12:47,580 --> 00:12:48,990 Well. 178 00:12:48,990 --> 00:12:51,720 All that is fine. We've defined our protocol and 179 00:12:51,720 --> 00:12:58,100 we've set the delegate, but somewhere in our THCustomView implementation, 180 00:12:58,100 --> 00:13:03,670 we need to instruct it that it needs to delegate that buttonPressed method. 181 00:13:03,670 --> 00:13:06,050 We aren't delegating that responsibility anywhere. 182 00:13:07,260 --> 00:13:11,730 So, as you can see, in this buttonPressed method, we're simply setting the text. 183 00:13:11,730 --> 00:13:17,752 So this is the last piece of the puzzle where we check our delegate object, 184 00:13:17,752 --> 00:13:23,150 so we'll say, if self.delegate 185 00:13:23,150 --> 00:13:28,460 responds to selector, so here we're checking to see 186 00:13:28,460 --> 00:13:33,620 if our delegate actually has this method. Does it have this 187 00:13:33,620 --> 00:13:38,880 method implemented, buttonPressed and if it does, 188 00:13:43,580 --> 00:13:49,950 then let's delegate that buttonPressed method, to the method of our delegate. 189 00:13:52,440 --> 00:13:57,950 So there is another method, called perform selector. 190 00:13:57,950 --> 00:14:02,570 So if you were passing an argument, you could use perform selector with object. 191 00:14:02,570 --> 00:14:05,010 In our case, we are not passing an argument so 192 00:14:05,010 --> 00:14:11,342 we will just say perform selector and then add selector, buttonPressed. 193 00:14:13,680 --> 00:14:21,330 So basically what this is doing here is performing this method of our delegate. 194 00:14:21,330 --> 00:14:26,740 And in this case, our delegate is our view controller, could it be something else? 195 00:14:26,740 --> 00:14:33,070 Sure, it could be any other class. And I will say else, 196 00:14:33,070 --> 00:14:38,920 so if it doesn't respond to the buttonPressed 197 00:14:38,920 --> 00:14:46,420 method, then we're just gonna do our default action. 198 00:14:46,420 --> 00:14:49,030 You don't have to do this but I just wanted to show 199 00:14:49,030 --> 00:14:54,260 that you can have default behavior or you could have delegated behavior. 200 00:14:55,650 --> 00:14:58,884 So now if we run our application and I hit Press Me, 201 00:14:58,884 --> 00:15:04,140 you'll notice that it says, button pressed: view controller, as it should. 202 00:15:05,530 --> 00:15:10,060 So going back to our code, one last thing that you want to note is 203 00:15:10,060 --> 00:15:16,280 that in our protocol we can define some of the methods as optional. 204 00:15:16,280 --> 00:15:20,190 As you notice that when we didn't define any of these methods 205 00:15:20,190 --> 00:15:23,050 as optional, the compiler complains saying 206 00:15:23,050 --> 00:15:26,191 that we hadn't implemented the buttonPressed method. 207 00:15:27,220 --> 00:15:30,560 So, how do you define it as optional? Well, you can 208 00:15:30,560 --> 00:15:35,730 just simply put the keyword @optional and basically it'll say whatever 209 00:15:35,730 --> 00:15:41,860 methods follow this @optional definition these methods will be optional. 210 00:15:41,860 --> 00:15:48,150 So now if we go back to our view controller implementation and I remove the 211 00:15:48,150 --> 00:15:51,510 implementation of the buttonPressed method, you'll notice 212 00:15:51,510 --> 00:15:54,430 that I don't get a compiler warning anymore. 213 00:15:54,430 --> 00:15:56,950 And if I run my application, 214 00:15:56,950 --> 00:16:01,812 it's simply going to use the default behavior. 215 00:16:01,812 --> 00:16:05,700 Basically, buttonPressed custom view, so that buttonPressed custom view 216 00:16:05,700 --> 00:16:09,290 is coming from my custom view and not the delegate. 217 00:16:09,290 --> 00:16:10,250 So there you have it. 218 00:16:10,250 --> 00:16:11,770 This is what delegates are all about. 219 00:16:11,770 --> 00:16:16,720 They're about delegating control or responsibility to another class. 220 00:16:16,720 --> 00:16:19,310 Now this doesn't have to be between views 221 00:16:19,310 --> 00:16:22,120 or controls, this could be between view controllers or 222 00:16:22,120 --> 00:16:23,870 your custom class. 223 00:16:23,870 --> 00:16:25,980 So, don't think that you're restricted to 224 00:16:25,980 --> 00:16:29,619 just UIView subclasses when creating a delegate.