views:

24079

answers:

5

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

But how do I create them?

+63  A: 

An Objective-C delegate is just an object (generally any 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];
}

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 easy and commonly used for delegates.

2) A Formal Protocol

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

@protocol NSWindowNotifications
@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 doesn't mess with NSObject and can provide better tool support.

Jesse Rusak
My question actually was how to create the windowDidMove method, how it got triggered how you can extend your class with Delegate Protocols, how those classes how implement the protocol gets called, etc..
Andy Jacobs
...and jder's reply seems to answer your question.
Can Berk Güder
Hillegass: 3rd edition page 108. 2nd edition page 118
Abizern
that was really helpful.
nont
+2  A: 

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.

Hope that helps,

--Tom

Tom Andersen
+2  A: 

Jonathan Sterling is good describing on his article. I think if you are still wondering that how is it working delegates. You should look his article.

Using custom delegates in Objective-C

fyasar
that link changed...now its http://jonsterling.github.com/2009/08/01/using-custom-delegates-in-objective-c.html
Sijo
Thanks for your notification.
fyasar
+3  A: 

I've also written about working with delegates from the iPhone perspective:

The Basics of Working with Delegates

John
+1  A: 

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.

umop