斗士狗 2009-03-09 16:06 采纳率: 0%
浏览 430
已采纳

如何在 Objective-C 中创建代表?

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

But how do I create them?

转载于:https://stackoverflow.com/questions/626898/how-do-i-create-delegates-in-objective-c

  • 写回答

19条回答 默认 最新

  • elliott.david 2009-03-09 16:16
    关注

    An Objective-C delegate is an object that has been assigned to the delegate 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.

    For example, suppose you have an 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 essentially 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 simply 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.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(18条)

报告相同问题?

悬赏问题

  • ¥15 如何在炒股软件中,爬到我想看的日k线
  • ¥15 51单片机中C语言怎么做到下面类似的功能的函数(相关搜索:c语言)
  • ¥15 seatunnel 怎么配置Elasticsearch
  • ¥15 PSCAD安装问题 ERROR: Visual Studio 2013, 2015, 2017 or 2019 is not found in the system.
  • ¥15 (标签-MATLAB|关键词-多址)
  • ¥15 关于#MATLAB#的问题,如何解决?(相关搜索:信噪比,系统容量)
  • ¥500 52810做蓝牙接受端
  • ¥15 基于PLC的三轴机械手程序
  • ¥15 多址通信方式的抗噪声性能和系统容量对比
  • ¥15 winform的chart曲线生成时有凸起