Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I know how delegates work, and I know how I can use them.

But how do I create them?

share|improve this question

6 Answers

up vote 385 down vote accepted

An Objective-C delegate is just an object that has been assigned as a delegate of another. There's no special process for creating them; you simply define a class that implements the delegate methods you're interested in. (Though with delegates that use a formal protocol, you must declare your delegate to implement that protocol; see below.)

For example, suppose you have an NSWindow. If you'd like to implement its delegate's windowDidMove: method, you could create a class like this:

@implementation MyClass
- (void)windowDidMove:(NSNotification*)notification { 
    // ... 
}
@end

Then you could create an instance of MyClass and assign it as the window's delegate:

MyClass *myDelegate = [[MyClass alloc] init];
[window setDelegate: myDelegate];

On the NSWindow side, it probably has code similar to this to see if the delegate responds to the windowDidMove: message using respondsToSelector: and send it if appropriate.

if([[self delegate] respondsToSelector:@selector(windowDidMove:)]) {
    [[self delegate] windowDidMove:notification];
}

The delegate property itself is typically declared weak (in ARC) or assign (pre-ARC) to avoid retain loops, since the delegate of an object often holds a strong reference to that object. (For example, a view controller is often the delegate of a view it contains.)

To define your own delegates, you'll have to declare their methods somewhere. There are two basic approaches, discussed in the Apple Docs on protocols:

1) An Informal Protocol

This can be done, as NSWindow does, in a category on NSObject. For example, continuing the example above, this is paraphrased from NSWindow.h:

@interface NSObject(NSWindowNotifications)
- (void)windowDidMove:(NSNotification *)notification;
// ... other methods here
@end

You would then use -respondsToSelector:, as described above, when calling this method. Delegates simply implement this method, and they're done. This method is straight-forward and common in Apple's libraries, but new code should use the more modern approach below.

2) A Formal Protocol

The newer option is to declare a formal protocol. The declaration would look like this:

@protocol NSWindowNotifications <NSObject>
@optional
- (void)windowDidMove:(NSNotification *)notification;
// ... other methods here
@end

This is analogous to an interface or abstract base class, as it creates a special type for your delegate, NSWindowNotifications in this case. Delegate implementors would have to adopt this protocol:

@interface MyDelegate <NSWindowNotifications>
// ...
@end

And then implement the methods in the protocol. For methods declared in the protocol as @optional (like most delegate methods), you still need to check with -respondsToSelector: before calling a particular method on it. Apple recommends this method, because it is more precise, doesn't mess with NSObject and can provide better tool support.

Speed Optimizations

Instead of checking whether a delegate responds to a selector every time we want to message it, you can cache that information when delegates are set. One very clean way to do this is to use a bitfield, as follows:

@protocol SomethingDelegate <NSObject>
@optional
- (void)something:(id)something didFinishLoadingItem:(id)item;
- (void)something:(id)something didFailWithError:(NSError *)error;
@end

@interface Something : NSObject
@property (nonatomic, weak) id <SomethingDelegate> delegate;
@end

@implementation Something {
  struct {
    unsigned int didFinishLoadingItem:1;
    unsigned int didFailWithError:1;
  } delegateRespondsTo;
}
@synthesize delegate;

- (void)setDelegate:(id <JSSomethingDelegate>)aDelegate {
  if (delegate != aDelegate) {
    delegate = aDelegate;

    delegateRespondsTo.didFinishLoadingItem = [delegate respondsToSelector:@selector(something:didFinishLoadingItem:)];
    delegateRespondsTo.didFailWithError = [delegate respondsToSelector:@selector(something:didFailWithError:)];
  }
}
@end

Then, in the body, we can check that our delegate handles messages by accessing our delegateRespondsTo struct, rather than by sending -respondsToSelector: over and over again.

share|improve this answer
11  
...and jder's reply seems to answer your question. – Can Berk Güder Mar 9 '09 at 16:37
6  
Hillegass: 3rd edition page 108. 2nd edition page 118 – Abizern Mar 9 '09 at 16:42
2  
the "Apple Docs on protocols" link is out of date. Here is the new link to apple's docs on protocols: developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/… – Matt Jan 25 '11 at 19:03
1  
Link broken, here is new link developer.apple.com/library/mac/#documentation/cocoa/Conceptual/… – Codler Feb 5 '12 at 9:47
3  
Won't the caching of respondsToSelector fail if the object has methods added after the caching is set up? There are ways of changing the behaviour of a class at any time, even well after the application is launched. – Tom Andersen Jul 3 '12 at 17:49
show 9 more comments

The approved answer is great, but if you're looking for a 1 minute answer try this:

MyClass.h file should look like this (add delegate lines with comments!)

#import <BlaClass/BlaClass.h>

@class MyClass;             //define class, so protocol can see MyClass
@protocol MyClassDelegate   //define delegate protocol
    - (void) myClassDelegateMethod: (MyClass *) sender;  //define delegate method to be implemented within another class
@end //end protocol

@interface MyClass : NSObject {
}
@property (nonatomic, weak) id <MyClassDelegate> delegate; //define MyClassDelegate as delegate

@end

MyClass.m file should look like this

#import "MyClass.h"
@implementation MyClass 
@synthesize delegate; //synthesise  MyClassDelegate delegate

- (void) myMethodToDoStuff {
    [self.delegate myClassDelegateMethod:self]; //this will call the method implemented in your other class    
}

@end

To use your delegate in another class (UIViewController called MyVC in this case) MyVC.h:

#import "MyClass.h"
@interface MyVC:UIViewController <MyClassDelegate> { //make it a delegate for MyClassDelegate
}

MyVC.m:

myClass.delegate = self;          //set its delegate to self somewhere

Implement delegate method

- (void) myClassDelegateMethod: (MyClass *) sender {
    NSLog(@"Delegates are great!");
}
share|improve this answer
1  
Quick and easy answer. Thanks! :) – anum90 Dec 5 '12 at 18:25
Great to use this answer as a quick reference. But why is the delegate property in your MyClass.h marked as 'IBOutlet'? – Arno van der Meer Apr 25 at 7:16
@ArnovanderMeer Good catch! I can't remember why. I need it in my project but not in this example, I removed it. thx – Tibidabo Apr 28 at 13:05

When using the formal protocol method for creating delegate support, I've found that you can ensure proper type checking (albeit, runtime, not compile time) by adding something like:

if (![delegate conformsToProtocol:@protocol(MyDelegate)]) {
    [NSException raise:@"MyDelegate Exception"
                format:@"Parameter does not conform to MyDelegate protocol at line %d", (int)__LINE__];
}

in your delegate accessor (setDelegate) code. This helps minimize mistakes.

share|improve this answer

Maybe this is more along the lines of what you are missing:

If you are coming from a C++ like viewpoint, delegates takes a little getting used to - but basically 'they just work'.

The way it works is that you set some object that you wrote as the delegate to NSWindow, but your object only has implementations (methods) for one or a few of the many possible delegate methods. So something happens, and NSWindow wants to call your object - it just uses Objective-c's respondsToSelector method to determine if your object wants that method called, and then calls it. This is how objective-c works - methods are looked up on demand.

It is totally trivial to do this with your own objects, there is nothing special going on, you could for instance have an NSArray of 27 objects, all different kinds of objects, only 18 some of them having the method -(void)setToBue; The other 9 don't. So to call setToBlue on all of 18 that need it done, something like this:

for (id anObject in myArray)
{
  if ([anObject respondsToSelector:@selector(@"setToBlue")])
     [anObject setToBlue]; 
}

The other thing about delegates is that they are not retained, so you always have to set the delegate to nil in your MyClass dealloc method.

share|improve this answer

Please! check below simple step by step tutorial to understand how Delegates works in iOS.

Delegate in iOS

I have created two ViewControllers (for sending data from one to another)

  1. FirstViewController implement delegate (which provides data).
  2. SecondViewController declare the delegate (which will receive data).
share|improve this answer

I think all these answers make a lot of sense once you understand delegates. Personally I came from the land of C/C++ and before that procedural languages like Fortran etc so here is my 2 min take on finding similar analogues in C++ paradigm.

If I were to explain delegates to a C++/Java programmer I would say

What are delegates ? These are static pointers to classes within another class. Once you assign a pointer, you can call functions/methods in that class. Hence some functions of your class are "delegated" (In C++ world - pointer to by a class object pointer) to another class.

What are protocols ? Conceptually it serves as similar purpose as to the header file of the class you are assigning as a delegate class. A protocol is a explicit way of defining what methods needs to be implemented in the class who's pointer was set as a delegate within a class.

How can I do something similar in C++? If you tried to do this in C++, you would by defining pointers to classes (objects) in the class definition and then wiring them up to other classes that will provide additional functions as delegates to your base class. But this wiring needs to be maitained within the code and will be clumsy and error prone. Objective C just assumes that programmers are not best at maintaining this decipline and provides compiler restrictions to enforce a clean implementation.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.