Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>An Objective-C delegate is an object that has been assigned to the <code>delegate</code> property another object. To create one, you simply define a class that implements the delegate methods you're interested in, and mark that class as implementing the delegate protocol.</p> <p>For example, suppose you have an <code>UIWebView</code>. If you'd like to implement its delegate's <a href="https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIWebViewDelegate_Protocol/index.html#//apple_ref/occ/intfm/UIWebViewDelegate/webViewDidStartLoad:" rel="noreferrer"><code>webViewDidStartLoad:</code></a> method, you could create a class like this:</p> <pre><code>@interface MyClass&lt;UIWebViewDelegate&gt; // ... @end @implementation MyClass - (void)webViewDidStartLoad:(UIWebView *)webView { // ... } @end </code></pre> <p>Then you could create an instance of MyClass and assign it as the web view's delegate:</p> <pre><code>MyClass *instanceOfMyClass = [[MyClass alloc] init]; myWebView.delegate = instanceOfMyClass; </code></pre> <p>On the <code>UIWebView</code> side, it probably has code similar to this to see if the delegate responds to the <code>webViewDidStartLoad:</code> message using <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Protocols/NSObject_Protocol/Reference/NSObject.html#//apple_ref/occ/intfm/NSObject/respondsToSelector:" rel="noreferrer"><code>respondsToSelector:</code></a> and send it if appropriate.</p> <pre><code>if([self.delegate respondsToSelector:@selector(webViewDidStartLoad:)]) { [self.delegate webViewDidStartLoad:self]; } </code></pre> <p>The delegate property itself is typically declared <code>weak</code> (in ARC) or <code>assign</code> (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.)</p> <h2>Making Delegates for Your Classes</h2> <p>To define your own delegates, you'll have to declare their methods somewhere, as discussed in the <a href="http://www.google.ca/search?q=site:developer.apple.com+protocols+objective+c&amp;btnI" rel="noreferrer">Apple Docs on protocols</a>. You usually declare a formal protocol. The declaration, paraphrased from UIWebView.h, would look like this:</p> <pre><code>@protocol UIWebViewDelegate &lt;NSObject&gt; @optional - (void)webViewDidStartLoad:(UIWebView *)webView; // ... other methods here @end </code></pre> <p>This is analogous to an interface or abstract base class, as it creates a special type for your delegate, <code>UIWebViewDelegate</code> in this case. Delegate implementors would have to adopt this protocol:</p> <pre><code>@interface MyClass &lt;UIWebViewDelegate&gt; // ... @end </code></pre> <p>And then implement the methods in the protocol. For methods declared in the protocol as <code>@optional</code> (like most delegate methods), you need to check with <code>-respondsToSelector:</code> before calling a particular method on it. </p> <h3>Naming</h3> <p>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, <code>webViewDidStartLoad:</code> (first parameter is the web view) rather than <code>loadStarted</code> (taking no parameters) for example. </p> <h3>Speed Optimizations</h3> <p>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:</p> <pre><code>@protocol SomethingDelegate &lt;NSObject&gt; @optional - (void)something:(id)something didFinishLoadingItem:(id)item; - (void)something:(id)something didFailWithError:(NSError *)error; @end @interface Something : NSObject @property (nonatomic, weak) id &lt;SomethingDelegate&gt; delegate; @end @implementation Something { struct { unsigned int didFinishLoadingItem:1; unsigned int didFailWithError:1; } delegateRespondsTo; } @synthesize delegate; - (void)setDelegate:(id &lt;SomethingDelegate&gt;)aDelegate { if (delegate != aDelegate) { delegate = aDelegate; delegateRespondsTo.didFinishLoadingItem = [delegate respondsToSelector:@selector(something:didFinishLoadingItem:)]; delegateRespondsTo.didFailWithError = [delegate respondsToSelector:@selector(something:didFailWithError:)]; } } @end </code></pre> <p>Then, in the body, we can check that our delegate handles messages by accessing our <code>delegateRespondsTo</code> struct, rather than by sending <code>-respondsToSelector:</code> over and over again.</p> <h3>Informal Delegates</h3> <p>Before protocols existed, it was common to use a <a href="http://www.google.ca/search?q=site:developer.apple.com+category+objective+c&amp;btnI" rel="noreferrer">category</a> on <code>NSObject</code> to declare the methods a delegate could implement. For example, <code>CALayer</code> still does this:</p> <pre><code>@interface NSObject(CALayerDelegate) - (void)displayLayer:(CALayer *)layer; // ... other methods here @end </code></pre> <p>This essentially tells the compiler that any object might implement <code>displayLayer:</code>.</p> <p>You would then use the same <code>-respondsToSelector:</code> approach as described above to call this method. Delegates simply implement this method and assign the <code>delegate</code> 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 <code>NSObject</code> (which makes autocomplete less useful) and makes it hard for the compiler to warn you about typos and similar errors.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload