Start a free Courses trial
to watch this video
Tip 12
This video doesn't have any notes.
Related Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign upRelated Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign upHi. My named is Amit,@paradoxed on Twitter. 0:00 So today we're gonna talk about delegation. 0:03 Delegation is a very common design pattern used all over when programming an iOS app. 0:06 If you've done any of our courses like the Blog Reader project or the Ribbit 0:11 app, you've noticed that within the table 0:16 View Controller, you have the table view delegate. 0:18 And then if you've used a scroll view or a text field, 0:22 you've probably used a delegate to go along with that. 0:25 So we've used delegate all over the places but we've 0:28 never specifically addressed what is the delegate, a design pattern. 0:30 Now a delegate or a protocol is basically something that defines 0:35 a bunch of methods that can be implemented by any class. 0:40 It's the most common design pattern and it means, to delegate control. 0:44 So you 0:50 are basically giving over control and having 0:50 that class implement the functionality of that method. 0:53 So let's take a look at how you can 0:57 define a protocol, and then implement that in a class. 0:59 Alright, I've created a sample app over 1:04 here, and, basically it's a single view application. 1:06 Let me run the app. 1:11 And what you'll see is that there's a button here. 1:13 Which says, press me, and then a text is displayed on the text label. 1:16 So the way this app is designed is that if I go to the main story board you won't see 1:22 anything because it's just a simple view, so there is 1:27 our view controller and it has the main view in it. 1:31 And let me go to the ViewController.m and you'll see that 1:35 it has a property called THCustomView and 1:41 all I do is add this custom view as a sub view to my 1:46 main view. Now this custom view, let's head on over 1:51 to customview.h, as you can see the interface, all it has 1:55 is a method called set text where you can set the text of the 2:01 label in the custom view. 2:06 Now, the, this is assuming that you have created this custom view 2:10 that you want to reuse it in multiple places throughout your application. 2:14 And you do not want to give direct access to the button or the label. 2:19 You just want the person using the custom view to set the 2:23 text and then you want to control the look and feel and 2:27 the color and all the other attributes of the controls that are housed 2:31 within this custom view. Now of course, as a contrived example, 2:37 I'm just trying to drive home the point that if you create a complex view 2:42 that can be reused throughout your application or you're creating a third 2:47 party component so that other people can use it or opensource 2:52 this component. 2:57 And you don't want to give completely control over all the controls within that 2:58 custom view, then what happens is that when a button is pressed. 3:03 Now, it's assuming that you, you can, of course, expose the button press method 3:10 and set target actions to other view controllers, but the way this custom 3:17 control is designed is that you have a button press method with that, within the 3:22 custom view, so it's setting itself a text when the button is pressed. 3:27 Now, inside the THView controller.m, I actually 3:34 want to receive that button pressed event. 3:40 I want to know when that button was pressed within the custom 3:44 view, so that I can go ahead and call that set text method. 3:48 I can simply set the text, but that doesn't help me because 3:52 I want to set the text only if the button has been pressed. 3:55 Now how do, how does the custom view 4:00 instruct the THviewController that the button was pressed. 4:02 Right now there's no way of doing that unless we expose the button 4:07 as a public property. Right now it's a private property. 4:13 Both of these are private properties. 4:16 But let's say you've created a, a custom 4:20 view and you don't wanna expose these things 4:22 as, public properties because you don't want them 4:25 to manipulate the look and feel of your control. 4:28 So, in the init frame, basically, we are setting the frame for the 4:32 button and adding it as a sub-view and the same thing we're doing 4:35 for the label. 4:38 Now the only way we can do this is if we create a delegate object that 4:41 delegates the responsibility of the button-press method to its delegate. 4:47 So the only way we can do that is if we create a delegate object within our 4:53 custom view that would delegate the responsibility of the button 4:58 press method to its delegate. So how do we go 5:04 about doing that? Well let's take a look, so, the first 5:07 thing I would need in my interface is a delegate object. 5:11 So we'll say at property nonatomic, and this would be weak, this is the 5:16 perfect example of using a weak property you will see that in a little 5:22 bit why it's a weak property and not very strong. 5:29 So, I have defined this delegate which is of type id. 5:33 We, we don't specify exactly what this is, because we 5:39 don't know what kind of delegate it's going to be. 5:42 It could be a view controller, it could be another view, it 5:46 could be a table view controller, it could be a scroll view. 5:49 Anything could be a 5:53 delegate of this custom view. 5:54 We don't know what could be the delegate, that's why it's an id, which means that 5:56 the type of this object is going to be determined at run time. 6:01 So, the next thing we need to do is define a protocol. 6:08 Now a protocol as its, as the name states, is, is 6:11 a set of methods that can be implemented by a delegate. 6:15 So the delegate needs some sort of structure, the 6:21 delegate just can't be like, well I am going 6:25 to do x, y and z, no, the delegate 6:27 needs some set up instructions that it can implement. 6:30 So we need to define what those instructions look like. 6:34 So you need to declare the instructions, which is a 6:37 protocol, and then that protocol is implemented by your delegate. 6:40 So we will declare our protocol right here in our THCustomView. 6:47 So it's after the interface implementation. 6:53 So, as you can see, after the end, @end over here. 6:57 So we need to give our protocol a name. So, the protocol names are basically the 7:01 name of the class that needs a protocol followed by the suffix delegate. 7:06 Now, it's usually a protocol on NSObject, so we'll leave that as is. 7:13 And then we define our methods. 7:18 Now similarly, as you define methods in your @interface, you 7:20 can have class methods or you can have instance methods. 7:24 So I'll create a instance method called buttonPressed. 7:28 Now mind you, this can be called anything you want. 7:35 I'm simply calling it buttonPressed because we're 7:38 delegating that button pressed action to our delegate. 7:40 Alright, so now that we've defined our protocol, it's always 7:46 good practice to define what kind of delegate this is. 7:49 So, as you can see in these angle brackets 7:54 over here, you specified NSObject, which means that the 7:57 protocol is of type NF, NSObject. Similarly, you can mention 8:00 that this delegate should only be of type THView custom delegate. 8:07 You don't want the other class just implementing any kind of delegate 8:16 and hoping that this will work, cuz otherwise you'll get a run-time error. 8:20 At least when you put 8:25 this here, you will get a compiler warning if that delegate hasn't been specified. 8:26 We'll come to it when we actually define the delegate in the view controller. 8:33 So you'll get a better understanding of why I'm doing this. 8:38 Now of course, we're getting an error 8:42 here saying that, cannot find protocol declaration. 8:43 That's because our protocol is defined after 8:48 the@Interface, so one way we can prevent that 8:51 error is just cause copying the @protocol ThCustomViewDelegate. 8:57 Just as we define an @class, which is a forward declaration, that 9:02 hey, this is a class that's going to be implemented in the future. 9:06 Similarly we can specify a forward declaration for our protocol. 9:11 So basically we're telling the compiler that this is a forward 9:16 declaration for a protocol and we're gonna declare it later on somewhere. 9:20 And later on, in this case, is right after our @interface declaration. 9:25 So, here we have actually created our own, very own protocol. 9:30 Now you've must have seen these protocols with 9:35 table view controllers or scroll views or text fields. 9:38 There are so many delicates defined for you in the UIKit framework. 9:41 And here we are defining our very own delegate. 9:46 So let's go ahead and see how we can implement this delegate. 9:51 So, when we go back to our THViewController.m, and 9:55 here in our self.customView, we can refer to that delegate property. 10:01 So .customView.delegate 10:07 and here we can just specify self. 10:14 Because we're saying we are going to be the delegate for the custom view. 10:17 We're gonna take over the responsibility of that button 10:21 press method, or any other methods the protocol provides. 10:25 So, as you can see here, I get a compiler warning and if I click here it says 10:31 assigning id THCustomViewDelicate from incompatible type, so that's 10:37 why we specify the THCustomViewDelegate in angle brackets. 10:43 Because it's saying like, are you really haven't implemented this delegate. 10:49 And by implementing, we have to go to the 10:53 interface definition of our view controllers. 10:56 So let's go to the .h file. 10:59 And here is where we specify THCustomViewDelegate. 11:02 So that's where we need to specify it and as you can see, we get an error saying 11:08 that it cannot find the protocol. So let's Import our THCustomView. 11:14 So that error will go away. 11:23 And so now when we go back to 11:25 our implementation, we don't get the error anymore. 11:28 You know, it, it's satisfied that you're gonna be implementing this delegate. 11:32 Now, we get another warning here, saying 11:37 that method, buttonPressed in protocol not implemented. 11:39 That's because we have to implement the methods required 11:45 by our protocol. 11:48 So, here we'll go and define the button press method. 11:52 So we'll say self.customView set text. 12:01 And let's set the text, we'll say button pressed 12:08 view controller. 12:15 So, are we done? 12:20 Well, let's run our application and see if this works, 12:21 and it won't work but let me show you anyway. 12:26 So it says button pressed custom view, and 12:30 it should really be saying, button pressed view controller. 12:32 Let me remove this space here so that work's consistent. 12:36 So why doesn't it work? 12:41 We've set our delegates, we've set our button pressed methods. 12:42 Well. 12:47 All that is fine. We've defined our protocol and 12:48 we've set the delegate, but somewhere in our THCustomView implementation, 12:51 we need to instruct it that it needs to delegate that buttonPressed method. 12:58 We aren't delegating that responsibility anywhere. 13:03 So, as you can see, in this buttonPressed method, we're simply setting the text. 13:07 So this is the last piece of the puzzle where we check our delegate object, 13:11 so we'll say, if self.delegate 13:17 responds to selector, so here we're checking to see 13:23 if our delegate actually has this method. Does it have this 13:28 method implemented, buttonPressed and if it does, 13:33 then let's delegate that buttonPressed method, to the method of our delegate. 13:43 So there is another method, called perform selector. 13:52 So if you were passing an argument, you could use perform selector with object. 13:57 In our case, we are not passing an argument so 14:02 we will just say perform selector and then add selector, buttonPressed. 14:05 So basically what this is doing here is performing this method of our delegate. 14:13 And in this case, our delegate is our view controller, could it be something else? 14:21 Sure, it could be any other class. And I will say else, 14:26 so if it doesn't respond to the buttonPressed 14:33 method, then we're just gonna do our default action. 14:38 You don't have to do this but I just wanted to show 14:46 that you can have default behavior or you could have delegated behavior. 14:49 So now if we run our application and I hit Press Me, 14:55 you'll notice that it says, button pressed: view controller, as it should. 14:58 So going back to our code, one last thing that you want to note is 15:05 that in our protocol we can define some of the methods as optional. 15:10 As you notice that when we didn't define any of these methods 15:16 as optional, the compiler complains saying 15:20 that we hadn't implemented the buttonPressed method. 15:23 So, how do you define it as optional? Well, you can 15:27 just simply put the keyword @optional and basically it'll say whatever 15:30 methods follow this @optional definition these methods will be optional. 15:35 So now if we go back to our view controller implementation and I remove the 15:41 implementation of the buttonPressed method, you'll notice 15:48 that I don't get a compiler warning anymore. 15:51 And if I run my application, 15:54 it's simply going to use the default behavior. 15:56 Basically, buttonPressed custom view, so that buttonPressed custom view 16:01 is coming from my custom view and not the delegate. 16:05 So there you have it. 16:09 This is what delegates are all about. 16:10 They're about delegating control or responsibility to another class. 16:11 Now this doesn't have to be between views 16:16 or controls, this could be between view controllers or 16:19 your custom class. 16:22 So, don't think that you're restricted to 16:23 just UIView subclasses when creating a delegate. 16:25
You need to sign up for Treehouse in order to download course files.
Sign upYou need to sign up for Treehouse in order to set up Workspace
Sign up