I know there are a lot of similar questions here but I still need some clarification about this concept.
First of all let me start by saying that I do understand what protocols are and how to use them, what I'm having problem understanding is delegation. I do understand that delegation is when one object in a program acts on behalf of another object, sound very simple but hard to see the whole picture.
1- Is delegation just a way to let the compiler know where to look for the code that will be manipulating the object (UITableView etc.)?
2- Do delegation and protocols work together?
3- Can delegation exist without protocols? If yes, can you show me an example.
4- When we declare a protocol and a class conforms to it, can we say that this class conforming to the protocol is delegating on behave of the protocol?
How much of the above is true?
Thanks a lot
1- Is delegation just a way to let the compiler know where to look for the code that will be manipulating the object (UITableView etc.)?
No, delegation is a design pattern. It's just a concept.
2- Do delegation and protocols work together?
Yes they work well together and it's probably the best practice to use protocol for your delegate.
3- Can delegation exist without protocols? If yes, can you show me an example.
Yes you can. Delegation concept is just to remove intellect of an object and put it in the delegate. For exemple an UITableView does not know how many row it has, or what to do when a cell is clicked, so it asks to its delegate.
But the delegate is still another object.
It's better if it implements a particular protocol, but you can do it without.
For exemple :
I've a MyView that is a subview of a MyCustomViewController.
MyCustomViewController.h
- (void)myViewIsTouched;
MyView.h
#property (nonatomic, weak) MyCustomViewController *delegate
MyView.m
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[self.delegate myViewIsTouched];
}
There is no protocol in this exemple, but it's still a delegate.
(A better way is still using a protocol instead of declaring the method in the .h)
4- When we declare a protocol and a class conforms to it, can we say that this class conforming to the protocol is delegating on behave of the protocol?
I'm not sure about what're saying. But protocols and delegate are not the same thing. An object implementing a protocol does not mean that it's a delegate.
Delegation allows objects to be able to change their appearance / state based on changes in other parts of your application. Setting a
delegate property on an object will allow the compiler to do some
checks at build-time.
Delegation is often achieved by using protocols, since it allows the
delegate object to be of any class instead of a sub-class of a class
with specific behaviour.
Yes, but this would result in your classes becoming tightly coupled since Foo needs to know about Bar and vice-versa. Using protocols allows you to use any class, hence id property, resulting in a loosely coupled system.
Example:
#class Foo;
#interface Bar : NSObject
- (void)respondToSomeAction:(Foo *)obj;
#end
#implementation Bar
- (void)respondToSomeAction:(Foo *)obj {
NSLog("responding to %#",obj);
}
#end
#interface Foo : NSObject
#property (nonatomic, weak) Bar *delegate
#end
#implementation Foo
- (void)someActionTriggered {
[self.delegate respondToSomeAction:self]
}
#end
When a class conforms to a protocol, the class is compelled to adopt the behaviours of the protocol (implement the methods). It only becomes a delegate if it is given some task to do on behalf of another class, e.g. supply the number of rows in a table.
Related
In iOS, what prevents me from having a list of delegates for an object? I know that you are not supposed to do it, but I don't understand if it's just because it doesn't conform to the Delegate pattern or if there is some real technical issues by doing it. I'll explain what I refer to with an example:
Protocol:
#protocol MyDelegate <NSObject>
- (void) someMethod;
#end
Class Header:
#interface SomeClass : NSObject
// Correct use of delegate pattern
#property (nonatomic, weak) id<MyDelegate> delegate;
// Incorrect use of delegate pattern
#property (nonatomic, strong) NSArray<id<MyDelegate>> delegates;
#end
Class implementation:
#implementation SomeClass
// Correct use of delegate pattern
- (void) someMethodThatCallsDelegate {
...
[_delegate someMethod];
}
// Incorrect use of delegate pattern
- (void) someMethodThatCallsDelegate {
...
for(id<MyDelegate> delegate in _delegates) {
[delegate someMethod];
}
}
#end
In my own projects, I often find myself in a situation where several Objects want to know of some event. Typically in network classes. In these cases, I just use NSNotificationCenter instead, but the thought of just having a list of delegates for the object always appeals me (Since I'm also an Android programmer, where a Set of Listeners is completely normal). So, what are the reasons for not having a List of Delegates?
(I also understand that in many cases it's bad design to have more than one delegate for an object, but I'm talking about the cases where it's not, such as in netcode)
There is nothing to stop you doing this. In fact, this is probably what I use protocols for more than for delegates etc...
However, I'd think about what you call the objects and the protocol.
A delegate is some object that your main object "delegates" work to. A table view (for instance) knows it has to have a number of rows, sections, etc... but instead of calculating those itself it says "my delegate is going to do this work for me". It then allows the same tableview to interact with any delegate.
Your objects are obviously not like that as there are many of them. They may all have some common usage though. What is that usage? Is delegate the right word to use?
If they are all "Listeners" then it would make more sense to call the protocol Listener with a function someListenedToActionWasTriggered and to call the array listeners.
Right now I have a view controller that handles a lot of network requests. They are each a subclass of a NetworkRequest class and this view controller is the delegate of all of them. It implements one callback function, networkRequestDidFinish.
The problem is that all these network requests are separate objects, and they will all call that same function. What is the proper way to design this? Right now I go through a bunch of if statements in networkRequestDidFinish to see what kind of network request returned. It feels wrong though, but I am not sure what is conventional to do in this case.
Thanks.
One useful pattern here is to be sure that the delegate methods pass self to the view controller. It sounds like you might already be doing this - if you're using a series of if statements, you probably have a pointer to the relevant NetworkRequest. If you aren't, or are not sure, read on.
You see this pattern pretty much wherever delegation is used. As an arbitrary example, take the UITableViewDelegate protocol. The first argument of each of the delegate methods is a UITableView. For example:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
When a UITableView instance calls this delegate method, it passes self as that first argument. It does something like:
[self.delegate tableView:self heightForRowAtIndexPath:0];
Then, the delegate knows which UITableView it's dealing with, because it has a pointer dropped in its lap, as the argument tableView.
In your case, I would start by adding a parameter to the delegate method networkRequestDidFinish, changing its signature to:
- (void)networkRequestDidFinish:(NetworkRequest *)networkRequest
That way you can tell which instance of NetworkRequest has called the delegate method.
Already had that, or that's not good enough? Well, the next thing I'd say would be to consider whether you really need to perform different actions based on the actual class of the NetworkRequest instance that's calling the delegate method. If you're just passing along the data, the answer is probably no. For example:
- (void)networkRequestDidFinish:(NetworkRequest *)networkRequest {
[self processData:networkRequest.data];
}
That method doesn't care what class networkRequest really is. But you seem to care, since you're doing "a bunch of if statements." Then I would say that it might be a mistake to have them all hitting one delegate method. Instead, you might want to get rid of a delegate on NetworkRequest, and instead add a protocol to each of the subclasses of that class, specific to the subclass.
What?
Let's look at an example.
Imagine that one of the subclasses of NetworkRequest is FooNetworkRequest which, of course, requests foos. Its header might look like this:
// stuff...
#protocol FooNetworkRequestDelegate
- (void)fooNetworkRequestDidFinish:(FooNetworkRequest *)fooNetworkRequest;
#end
#interface FooNetworkRequest : NetworkRequest
#property (weak, nonatomic) id<FooNetworkRequestDelegate> delegate;
// stuff...
#end
You apply a similar treatment to all the other subclasses of NetworkRequest. Then, your view controller would adopt each of these protocols, and have a separate method for each subclass of NetworkRequest.
That still seems kind of dirty, right? It does to me. Maybe this is a hint that your view controller is trying to handle too many things at once. You should consider trying to spread out the responsibility for all these NetworkRequest subclasses to multiple view controller or model classes.
If that's not an option, you can at least make your view controller's source a little easier to read by using one or more categories. Put your view controller's main behavior in its .m file, as usual, and then create a category on that view controller that adopts the proper protocol(s) and handles the requests.
There are generally 2 nice procedures.
You can use block instead of the delegate. That means you can send a block to your request class either when instancing it or when you make the request.
Use a target/selector pair system to make it look kind of like adding a target to an UIButton. NSInvocation should do the trick.
I have used #protocols many times but I think I have been doing it wrong all the time. They have worked always well, but now I want to improve my level so I am trying to do it the better I can.
I always have created a delegate like this:
#protocol CommentViewDelegate;
#interface LZCommentView : UIView
#property (assign, nonatomic) id <CommentViewDelegate> delegate;
#end
#protocol CommentViewDelegate
-(void)showAndHideCommentView;
#end
Now, I have seen that almost all the delegate methods that I see send their own object. Something like this:
-(void)showAndHideCommentView:(LZCommentView *)commentView;
What is the difference between what I did and this? Is one of them better than the other? I have seen that almost everyone who does this, does not use the object in the ViewController.
Another question is, should I use <NSObject> in the #protocol definition?
And the last one, what is better create the #property with assign or strong?
Thank you
Generally, the object that you pass to the delegate can be used so that the same delegate class can be used in different contexts. This gives you more flexibility in cases when a delegate class could potentially be reused.
For example, if showAndHideCommentView needs to interact with a view being shown or hidden, it has two ways of doing it:
Get the view as an argument, or
Reference the view directly, knowing that this delegate is attached to a particular view.
Example of the first approach:
#implementation MyDelegate
-(void)showAndHideCommentView:(LZCommentView *)commentView {
if (isShowing) {
[commentView doSomething];
}
}
#end
Example of the second approach:
#implementation MyDelegate
-(void)showAndHideCommentView {
if (isShowing) {
[self.commentView doSomething];
}
}
#end
The first approach is more flexible than the second one, because it lets you reuse the same code.
According to Apple, it’s best practice to define your protocols to conform to the NSObject protocol, so the answer to your second question is "yes".
As far as the third question goes, the best way to declare delegate properties is with the weak attribute to avoid retain cycles.
1) You should always make your protocol conform to the NSObject protocol. This lets you make use of all of the methods in that protocol.
#protocol CommentViewDelegate <NSObject>
2) Unless you have a good reason to do otherwise, most properties for delegates should be defined as weak. This avoids reference cycles and it ensure the delegate is automatically set to nil if the delegate object is deallocated.
#property (nonatomic, weak) id<CommentViewDelegate> delegate;
3) It's best to include the object in the protocol methods because it offers the most flexibility. It also allows a class to be the delegate of more than one instance. Then the class can tell which instance the protocol method is being called for. Think of a view controller handling multiple buttons or having two or more table views.
I've seen this in some areas of code that I am working with.
searchBar.delegate = (id<UISearchBarDelegate>)self;
My question is...
Why not just make the current class a delegate of UISearchBar by adding <UISearchBarDelegate> in the interface of the class?
Are there times when the above code is better than having the class be a delegate?.
Both ways work for me, but I'd like to learn why I may want to use one over the other.
The cast approach could be considered a cheat. It would be used if the delegate class didn't want to publicly declare the protocol conformance (but then why is it being publicly set as the delegate). Or if the delegate class didn't implement all of the required methods so declaring the protocol conformance would result in warnings.
Generally the better approach is to declare the protocol conformance (either publicly (.h) or privately (.m)).
If you are not using the UISearchBarDelegate in your .h like
#interface ScaryBugData < UISearchBarDelegate>
#property (strong) UISearchBar * searchBar;
#end
then in your .m file then you must do the following to silence the warning
searchBar.delegate = (id<UISearchBarDelegate>)self;
I am working on a delegate pattern for authorization in my app.
Most things i've seen before use something like:
#property (weak) id<Delegate> delegate;
Does that make it weaker than say
#property (weak) UIViewController<Delegate> *delegate;
I realize i am asking for any pointer in the first one and in the second I am expecting a typed pointer. But i only want my delegate to be a UIViewController or subclass.
Can anyone explain the differences and pros and cons?
But I only want my delegate to be a UIViewController or subclass.
Then go for the second way - the first one indicates that it can be any object that conforms to the <Delegate> protocol.
There are not real pros or cons. The contract is just different. One says "I don't care what class it is as long as it conforms to that protocol" and the other says "I want a subclass of UIViewController which also conforms to the protocol".
The only thing here is that the idea of the "delegate" pattern in Cocoa is generally to give the client of your API a way to create an object that will customize the behavior of one or several other components.
Since you want this property to be a view controller, the semantic is more than just a delegate so I would not call it a delegate but a xxxViewController with "xxx" being the actual functional relationship between your object and that view controller.