How does a delegate work in objective-C?
- Does anyone know where I can find a good explanation/tutorial of what and how an application delegate works in
objective-C
? - The two books I have don't dwell on
delegates
enough and do not explain them very well for me to truly understand their power and function.
Solution 1:
When in doubt, check the docs!
Basically, delegation is a way of allowing objects to interact with each other without creating strong interdependencies between them, since this makes the design of your application less flexible. Instead of objects controlling one another, they can have a delegate which they send (or delegate) messages to, and the delegate does whatever they do, in order to respond and act to this message, and then usually return something back to the other object.
Delegation is also a better alternative to subclassing. Instead of you having to create your own custom classes to slightly alter the way that other objects behave, or pass them data, delegation allows objects to send messages to their delegates to do work for them without the overhead of creating subclasses to make minor changes to other objects.
Of course, the main disadvantage of delegation is that the delegate methods available are dependent on what the Apple engineers foresee as being useful and what common implementations they expect people to need, which imposes a restriction on what you can achieve. Although, as Quinn Taylor pointed out, this is specific to the Cocoa frameworks and so doesn't apply in all situations.
If delegation is an option over subclassing, then take it, because it's a much cleaner way to manage your code and interactions between objects.
Solution 2:
As described above, a delegate is not a feature of iOS or Objective-C, but just a programming technique and requires no specific language support.
A class (e,g, classA) may be written such that its getData and doSomething methods can be implemented not by itself, but by a delegate (perhaps because classA doesn't know what the data will be or what it will have to do).
To achieve this, classA provides a property, usually called delegate, (which is just a pointer to the class - the delegate - that implements the delegated methods) and then, when it wants to call those methods, it actually calls the methods in the delegate:
[self.delegate getData];
and
[self.delegate doSomething];
self.delegate
may be initially set to self
:
self.delegate = self;
i.e. classA implements it's own version of these methods, unless they are delegated.
Any other class, wanting to be the implementor of the methods (i.e. to be the delegate and possibly override classA's default implementation), would first set classA's delegate to be itself. so if classB wanted to be the delegate for these methods, in classB, we would have:
classA.delegate = self;
So when classA calls these delegated methods, it's actually calling classB to implement these methods, without knowing anything about classB or even that it exists and classB doesn't have to sub-class classA.
The limitation is that classB can only override methods which classA wants to delegate - with subclassing, you can override any method.
Protocols are used to formalise the delegation process by defining a list of methods which either must be implemented by the delegate (the delegator provides no default version of the method and the method must be implemented somewhere) or can be optionally implemented by the delegate (i.e. the delegator has it's own version or it does not matter if the method is not implemetned).
Solution 3:
Delegates are a design pattern; there is no special syntax or language support.
A delegate is just an object that another object sends messages to when certain things happen, so that the delegate can handle app-specific details the original object wasn't designed for. It's a way of customizing behavior without subclassing.
Solution 4:
I try to elaborate it through simple program
Two Classes
Student.h
#import <Foundation/Foundation.h>
@interface Student : NSObject
@property (weak) id delegate;
- (void) studentInfo;
@end
Student.m
#import "Student.h"
@implementation Student
- (void) studentInfo
{
NSString *teacherName;
if ([self.delegate respondsToSelector:@selector(teacherName)]) {
teacherName = [self.delegate performSelector:@selector(teacherName)];
}
NSLog(@"\n Student name is XYZ\n Teacher name is %@",teacherName);
}
@end
Teacher.h
#import <Foundation/Foundation.h>
#import "Student.h>
@interface Teacher: NSObject
@property (strong,nonatomic) Student *student;
- (NSString *) teacherName;
- (id) initWithStudent:(Student *)student;
@end
Teacher.m
#import "Teacher.h"
@implementation Teacher
- (NSString *) teacherName
{
return @"ABC";
}
- (id) initWithStudent:(Student *)student
{
self = [ super init];
if (self) {
self.student = student;
self.student.delegate = self;
}
return self;
}
@end
main.m
#import <Foundation/Foundation.h>
#import "Teacher.h"
int main ( int argc, const char* argv[])
{
@autoreleasepool {
Student *student = [[Student alloc] init];
Teacher *teacher = [[Teacher alloc] initWithStudent:student];
[student studentInfo];
}
return 0;
}
EXPLANATION :::
-
From main method when initWithStudent:student will execute
1.1 Teacher's object's property 'student' will be assigned with student object.
1.2 self.student.delegate = self means student object's delegate will points to teacher object
-
From main method when [student studentInfo] will be called
2.1 [self.delegate respondToSelector:@selector(teacherName)] Here delegate already points to teacher object so it can invoke 'teacherName' instance method.
2.2 so [self.delegate performSelector:@selector(teacherName)] will execute easily.
It looks like Teacher object assign delegate to student object to call it's own method.
It is a relative idea, where we see that student object called 'teacherName' method but it is basically done by teacher object itself.