How Does a Delegate Work in Objective-C

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.

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.

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.

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.

how delegates works and delegates work flow in objective-c

First of all let me point out that you do not need to create a separate instance variable with an underscore prefix when you use @property to declare a property. You can access this property using self.delegate and it also automatically creates _delegate for you. Because _delegate is already created using @property you can take out the duplicate declaration.

Secondly, you can move <SampleProtocolDelegate> to the property declaration, you should also set it to weak to avoid a retain cycle. See: Why use weak pointer for delegation?. So your interface would end up looking like this:

@interface SampleProtocol : NSObject

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

-(void)startSampleProcess;

@end

By putting <SampleProtocolDelegate> between 'id' and 'delegate',
only objects that conform to the SampleProtocolDelegate can set themselves as the delegate of the object (it means: any object that conforms to this protocol). And the SampleProtocol object can safely assume that it can call the protocol methods on its delegate.

How do delegates work in objective c?

Try this:

ViewController.h

#import <UIKit/UIKit.h>

@class ViewController;

@protocol testDelegate
-(void)sayHi;
@end

@interface ViewController : UIViewController

- (IBAction)button:(id)sender;
@property (weak, nonatomic)id <testDelegate> delegate;

@end

ViewController.m

#import "ViewController.h"
#import "DelegateController.h"


@interface ViewController ()
@property (nonatomic, strong) DelegateController *dc;
@end

@implementation ViewController

- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
_dc = [[DelegateController alloc] init];
[self setDelegate:_dc];
}

- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

- (IBAction)button:(id)sender
{
[self.delegate sayHi];
}
@end

DelegateController.h

@interface DelegateController : UIViewController <testDelegate>

@end

DelegateController.m

#import "DelegateController.h"

@interface DelegateController ()

@end

@implementation DelegateController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
NSLog(@"init");
}
return self;
}
-(void)viewDidLoad
{
[super viewDidLoad];
}

-(void)sayHi
{
NSLog(@"hi");
}

@end

Delegates in objective c

Delegates in Objective-C are merely a concept, not some kind of implementation artifact (like in C#). A delegate in Objective-C (better: Cocoa) is basically an object, which is notified by whoever uses it as its "delegate" of certain events occuring. Delegates may also be asked to perform certain tasks on behalf of the host object. The interface a delegate is required to implement is often formalized by a protocol.

@protocol ActionDelegate 

- (void) actionDidStart: (id) aSender;
- (void) actionDidEnd: (id) aSender;

@end

@interface Action: NSObject {
id<ActionDelegate> delegate;
}

@property (nonatomic,assign) id<ActionDelegate> delegate;

@end

Delegates in C#, on the other hand, are an implementation artifact. There is a dedicated delegate keyword to declare delegate types and to create actual delegate instances.

class Action {

delegate void ActionDidStartDelegate(Action sender);
delegate void ActionDidEndDelegate(Action sender);

...
}

(my C# is a bit rusty, so the syntax may be off here, sorry; and in real life, one would probably use events in situations like the above rather than raw delegates). Basically, a C# delegate is akin to a Python method object.

You might be able to use the new code block feature of Objective-C to emulate delegates. Not having used this feature (yet), I cannot comment on this. Another way to get something like that would be to use plain function pointers.

typedef void (*callback_function)();

- (void) doSomethingWithCallback: (callback_function) func {
...
func();
}

And of course, you can always use the method often employed by Cocoa itself: use an object and an associated method selector:

- (void) doSomethingWhenDonePerform: (SEL)aSelector onObject: (id) aReceiver {
...
[aReceiver perform: aSelector];
}

Objective-C, Delegate as Adapter Pattern: who is the adaptee?

I've found a solution in the official documentation, as I suspected there is no adaptee:
https://developer.apple.com/legacy/library/documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaDesignPatterns/CocoaDesignPatterns.html#//apple_ref/doc/uid/TP40002974-CH6-SW5



Related Topics



Leave a reply



Submit