Full Time Skeleton
Full Time Skeleton

Reputation: 1740

Delegates in IOS - Some clarification required

I'm only really beginning IOS development but have a few years dev of ASP.net through C#. To be honest I've never had a real need to understand delegates / events etc. before, I know that I'm using them when programming web.forms but a lot of the functionality is taken care of by the framework, behind the scenes.

So now that I'm developing in IOS I'm forced to try to understand how they function (I'm presuming here that the theory of delegates / events is the same across languages, maybe I'm wrong). Anyway, the following line of code in IOS:

 if ([self.delegate respondsToSelector:@selector(startImporting:)])
 {
            [self.delegate startImporting:self];
 }

Am I right in thinking that, in pseudo code, it means something along the lines of:

If the method/class calling this method has a method in it called 'startImporting' then call the method 'startImporting' within the calling class.

Hope that's clear. If that's the case then would it essentially be the same as having a static method in C# that you could call with something like:

myImportClass.startImporting();

Presumably not, or that's how it would be done. So, am I missing the whole point of delegates, their benefits etc? I've read what they are over and over and while it makes sense, it never clicks, I never (in web forms anyway) have really seen the benefit of using them.

This becomes increasingly important as I'm moving to using lambda expressions in .net and they're closely linked to delegates in C# so while I can just start using them, I'd prefer to know why and what benefit delegates actually are.

Upvotes: 10

Views: 8844

Answers (3)

Durai Amuthan.H
Durai Amuthan.H

Reputation: 32320

delegates are useful in getting callbacks from other class

so why to use delegate: that is we call a method on a class... that's normal... if we want the instantiated class to let us call back... that's where delegates comes in handy...

simple example: You download songs from a site using a method on one class once the class completes downloading you want the class to let you know.

 //protocol declaration
  @protocol DownloadProtocol <NSObject>
  -(void)OnFinish;
  @end

//SOng download class
@interface songs
@property(Strong,nonatomic) id<DownloadProtcol> delegate;
-(void)Download;
@end
@implementation songs
-(void)Download
{

///the code to download goes here

[self callTheCallingClass];

}

-(void)CallTheCallingClass
{
 [self.delegate OnFinish];
}
@end

//
@interface mainclass<DownloadProtocol>

@end

@implementation mainclass

-(void)viewDidload
{
Songs *s=[[SOngs alloc]init];
s.delegate=self;
[s download];
}
-(void)OnFinish
{
  NSlog(@"Called");
}
@end
  1. see the delegation is achieved through protocol in objective c. I think you can understand the syntax of it.

  2. In the songs class we create a property for that protocol. we keep it the type as ID... because the type is not known at compile time.

  3. in the songs class once we complete the download we call the protocol method...

  4. In the main class first we adopt the protocol syntax class the above is syntax of that

  5. the we instantiate the songs class

  6. then assign the main class object(self) to delegate of songs class

  7. then we have to apply the protocol class in .m by adding method name from protocol

  8. so from now on whenever songs class call the protocol method through delegate instance variable....out protocol method adoption on main class gets run

try this code hope it helps...

if you want more info on this topic google it as delegate design pattern

the main benefit is it promotes loosely coupled programming...

Upvotes: 0

Fabian Kreiser
Fabian Kreiser

Reputation: 8337

The delegation pattern in Cocoa is used to inform (report progress, etc.) or query (ask for credentials, etc.) another object without knowing much about it.

Typically, you use a protocol to define what methods you will call on the delegate and the delegate then needs to conform to that protocol. You can also add methods that the delegate doesn't need to implement (optional). When you do so, you'll have to call -respondsToSelector:, because you don't know whether the delegate wants the particular method to be called or not.

An example:
You have a class that produces something, let's call it Machine and a worker of the class Worker. The machine needs to be adjusted for the task:

Machine *machine = [[Machine alloc] init];
[machine prepareWithParameters:myParameters];

Now that we have the machine we want to produce a massive amount of Stuff:

[machine produceStuff];

Okay, we're done. But how do we know when an unit of Stuff has been produced? We could have our worker constantly standing beside our machine and wait:

while (![machine isFinished]) {
    if ([machine didProduceStuff]) {
        Stuff *stuff = [machine producedStuff];
        [self doSomethingWithStuff:stuff];
    }
    else {
        // Get a very large coffee...
    }
}

Wouldn't it be great if the machine did inform us automatically, when it's done with producing an unit of Stuff?

@protocol MachineDelegate <NSObject>
@optional
    - (void) machine:(Machine *)machine didProduceStuff:(Stuff *)stuff;
@end

Let's add the worker as a delegate of machine:

Worker *worker;
Machine *machine = [[Machine alloc] init];
[machine prepareWithParameters:myParameters];
[machine setDelegate:worker]; // worker does conform to <MachineDelegate>

[machine produceStuff];

When Machine is done producing something, it will then call:

if ([[self delegate] respondsToSelector:@selector(machine:didProduceStuff:)])
    [[self delegate] machine:self didProduceStuff:stuff];

The worker will then receive this method and can do something:

- (void) machine:(Machine *)machine didProduceStuff:(Stuff *)stuff {
    [self doSomethingWithStuff:stuff];
    if ([machine isFinished])
        [self shutDownMachine:machine];

}

Isn't that much more efficient and easier for the worker? Now he can do something more productive than standing besides the machine while the machine is still producing. You could now add even more methods to MachineDelegate:

@protocol MachineDelegate <NSObject>
@required
    - (void) machineNeedsMaintenance:(Machine *)machine;
    - (void) machine:(Machine *)machine fatalErrorOccured:(Error *)error;
    - (BOOL) machine:(Machine *)machine shouldContinueAfterProductionError:(Error *)error;
@optional
    - (void) machineDidEnterEcoMode:(Machine *)machine;
    - (void) machine:(Machine *)machine didProduceStuff:(Stuff *)stuff;
@end

Delegates can also be used to change the behavior of an object without subclassing it:

@protocol MachineDelegate <NSObject>
@required
    - (Color *) colorForStuffBeingProducedInMachine:(Machine *)machine;
    - (BOOL) machineShouldGiftWrapStuffWhenDone:(Machine *)machine;
@end

I hope I could help you understand the benefit of abstracting your code using delegates a little bit.

Upvotes: 45

aracknido
aracknido

Reputation: 11

Understanding the MVC model and the use of Protocols and notifications is critical to grasping the use and purpose of delegates. Think of them as types of responders for different events related to a specific action.

Hera are some useful links in stackOverflow:

Hope it helps

Upvotes: 1

Related Questions