What Is a "Delegate" in Objective C's iPhone Development

What is a delegate in Objective C's iPhone development?

See this discussion

A delegate allows one object to send messages to another object when an event happens. For example, if you're downloading data from a web site asynchronously using the NSURLConnection class. NSURLConnection has three common delegates:

 - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response

One or more of these delegates will get called when NSURLConnection encounters a failure, finishes successfully, or received a response from the web site, respectively.

How do I create delegates in Objective-C?

An Objective-C delegate is an object that has been assigned to the delegate property another object. To create one, you define a class that implements the delegate methods you're interested in, and mark that class as implementing the delegate protocol.

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

@interface MyClass<UIWebViewDelegate>
// ...
@end

@implementation MyClass
- (void)webViewDidStartLoad:(UIWebView *)webView {
// ...
}
@end

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

MyClass *instanceOfMyClass = [[MyClass alloc] init];
myWebView.delegate = instanceOfMyClass;

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

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

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.)

Making Delegates for Your Classes

To define your own delegates, you'll have to declare their methods somewhere, as discussed in the Apple Docs on protocols. You usually declare a formal protocol. The declaration, paraphrased from UIWebView.h, would look like this:

@protocol UIWebViewDelegate <NSObject>
@optional
- (void)webViewDidStartLoad:(UIWebView *)webView;
// ... other methods here
@end

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

@interface MyClass <UIWebViewDelegate>
// ...
@end

And then implement the methods in the protocol. For methods declared in the protocol as @optional (like most delegate methods), you need to check with -respondsToSelector: before calling a particular method on it.

Naming

Delegate methods are typically named starting with the delegating class name, and take the delegating object as the first parameter. They also often use a will-, should-, or did- form. So, webViewDidStartLoad: (first parameter is the web view) rather than loadStarted (taking no parameters) for example.

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 <SomethingDelegate>)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.

Informal Delegates

Before protocols existed, it was common to use a category on NSObject to declare the methods a delegate could implement. For example, CALayer still does this:

@interface NSObject(CALayerDelegate)
- (void)displayLayer:(CALayer *)layer;
// ... other methods here
@end

This tells the compiler that any object might implement displayLayer:.

You would then use the same -respondsToSelector: approach as described above to call this method. Delegates implement this method and assign the delegate property, and that's it (there's no declaring you conform to a protocol). This method is common in Apple's libraries, but new code should use the more modern protocol approach above, since this approach pollutes NSObject (which makes autocomplete less useful) and makes it hard for the compiler to warn you about typos and similar errors.

How does a delegate work in objective-C?

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.

What exactly are protocols and delegates and how are they used in IOS?

Protocols are a way to specify a set of methods you want a class to implement if it wants to work with one of your classes. Delegates and Data Sources like UITableViewDelegate and UITableViewDataSource are protocols indeed.

You specify a protocol this way:

@protocol MyProtocol <NSObject>

- (void)aRequiredMethod;

@required
- (void)anotherRequiredMethod;

@optional
- (void)anOptionalMethod;

@end

Methods declared after the @required or before any other specifier are required and the classes that want to use your protocol need to implement all of them. You can also declare some optional methods by declaring them after the @optional specifier.

You then can specify that a class "conforms" to a protocol (implements the required methods) in the interface of the class:

@interface MyClass <MyProtocol>

@end

You usually keep a reference to an object conforming to a protocol using a property. For example, to keep track of a delegate:

@property (nonatomic, weak) id<MyProtocol> delegate;

At this point, in your code, you just have to call the method you want to call on the object that you're keeping reference of and that implements your protocol as you would with any other method:

[self.delegate aRequiredMethod];

To check whether an object conforms to a protocol you can call

[self.delegate conformsToProtocol:@protocol(MyProtocol)]

To check whether an object implements a method you can call

[self.delegate respondsToSelector:@selector(anOptionalMethod)]

For more information, check the Apple's guide Working With Protocols.

Delegates in Objective-C (iphone development) best practice

You may find this link helpful, since it seems to be talking about a similar situation to yours where the author used delegates:

http://css.dzone.com/articles/do-not-publishcreating-your

Also, this Apple page might be a good read as well if you are curious about different ways in which objects can communicate with each other:

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CocoaFundamentals/CommunicatingWithObjects/CommunicateWithObjects.html

The best way to be confident that you are using the right strategy, beyond simply asking other people for confirmation, is to make sure you understand the definition and purpose behind delegation, and then analyze your code from that perspective to see if its a good fit for what you are trying to do. Excerpt from Wikipedia:

In software engineering, the
delegation pattern is a design pattern
in object-oriented programming where
an object, instead of performing one
of its stated tasks, delegates that
task to an associated helper object.
( http://en.wikipedia.org/wiki/Delegation_pattern )

Considering all that, I think you're on the right track with what you're currently doing.

Need of Delegation in iPhone Development or Objective C

Think of all the components that iOS and Cocoa provide you with. TableViews, TextFields, PopOvers...etc.

When the developers wrote these components, they couldn't possibly know all the various implementations that us developers were going to create using these components. But we need somehow to communicate with them in a generic way.

These components use delegates. The delegate is an implementation independent way of describing some behaviour that your component can conform to.

When UITableView need to find out what is the height of the rows, the UITableView only needs to know about UITableViewDelegate. It doesn't need to know about MyTableViewController, JohnsTableViewController, BobsTableViewController... etc.

So the delegate is decoupling the component from the implementation and the type.

Decoupling is a good thing. It makes maintaing and changing code a lot easier, and makes code reusable.

Difference between protocol and delegates?

A protocol, declared with the (@protocol syntax in Objective-C) is used to declare a set of methods that a class "adopts" (declares that it will use this protocol) will implement. This means that you can specify in your code that, "you don't care which class is used as long as it implements a particular protocol". This can be done in Objective-C as follows:

id<MyProtocol> instanceOfClassThatImplementsMyProtocol;

If you state this in your code, then any class that "conforms" to the protocol MyProtocol can be used in the variable instanceOfClassThatImplementsMyProtocol. This means that the code that uses this variable knows that it can use whichever methods are defined in MyProtocol with this particular variable, regardless of what class it is. This is a great way of avoiding the inheritance design pattern, and avoids tight coupling.

Delegates are a use of the language feature of protocols. The delegation design pattern is a way of designing your code to use protocols where necessary. In the Cocoa frameworks, the delegate design pattern is used to specify an instance of a class which conforms to a particular protocol. This particular protocol specifies methods that the delegate class should implement to perform specific actions at given events. The class that uses the delegate knows that its delegate coforms to the protocol, so it knows that it can call the implemented methods at given times. This design pattern is a great way of decoupling the classes, because it makes it really easy to exchange one delegate instance for another - all the programmer has to do is ensure that the replacement instance or class conforms to the necessary protocol (i.e. it implements the methods specified in the protocol)!

Protocols and delegates are not restricted only to Objective-C and Mac/iOS development, but the Objective-C language and the Apple frameworks make heavy use of this awesome language feature and design pattern.

Edit:

Here's an example. In the UIKit framework of Cocoa Touch, there is a UITextFieldDelegate protocol. This protocol defines a series of methods that classes which are delegates of a UITextField instance should implement. In other words, if you want to assign a delegate to a UITextField (using the delegate property), you'd better make sure that this class conforms to UITextFieldDelegate. In fact, because the delegate property of UITextField is defined as:

@property(nonatomic, weak) id<UITextFieldDelegate> delegate

Then the compiler will give warnings if you assign a class to it that doesn't implement the protocol. This is really useful. You have to state that a class implements a protocol, and in saying that it does, you're letting other classes know that they can interact in a particular way with your class. So, if you assign an instance of MyTextFieldDelegateClass to the delegate property of UITextField, the UITextField knows that it can call some particular methods (related to text entry, selection etc.) of your MyTextFieldDelegateClass. It knows this because MyTextFieldDelegateClass has said that it will implement the UITextFieldDelegate protocol.

Ultimately, this all leads to much greater flexibility and adaptability in your project's code, which I'm sure you'll soon realise after using this technology! :)



Related Topics



Leave a reply



Submit