Objective-C 协议(Protocols)

Objective-C 支持您定义协议,这些协议声明了预期用于特定情况的方法。在符合协议的类中实现协议。

举一个简单的例子,一个网络 URL 处理类,它将有一个协议,其中包含 processCompleted 委托方法等方法,一旦网络URL获取操作结束,该方法将通知调用类。

协议的语法如下:

  1. @protocol ProtocolName
  2. @required
  3. // list of required methods
  4. @optional
  5. // list of optional methods
  6. @end

关键字 @required 下的方法必须在符合协议的类中实现, @optional 关键字下的方法是可选的。

下面是符合协议的类的语法:

  1. @interface MyClass : NSObject <MyProtocol>
  2. ...
  3. @end

这意味着 MyClass 的任何实例将不仅响应接口中专门声明的方法,而且 MyClass 还提供 MyProtocol 中所需方法的实现。不需要在类接口中重新声明协议方法 - 采用协议就足够了。

如果需要一个类来采用多个协议,可以将它们指定为逗号分隔的列表。我们有一个委托对象,它保存实现协议的调用对象的引用。

如下面的实例

  1. #import <Foundation/Foundation.h>
  2. @protocol PrintProtocolDelegate
  3. - (void)processCompleted;
  4. @end
  5. @interface PrintClass :NSObject {
  6. id delegate;
  7. }
  8. - (void) printDetails;
  9. - (void) setDelegate:(id)newDelegate;
  10. @end
  11. @implementation PrintClass
  12. - (void)printDetails {
  13. NSLog(@"Printing Details");
  14. [delegate processCompleted];
  15. }
  16. - (void) setDelegate:(id)newDelegate {
  17. delegate = newDelegate;
  18. }
  19. @end
  20. @interface SampleClass:NSObject<PrintProtocolDelegate>
  21. - (void)startAction;
  22. @end
  23. @implementation SampleClass
  24. - (void)startAction {
  25. PrintClass *printClass = [[PrintClass alloc]init];
  26. [printClass setDelegate:self];
  27. [printClass printDetails];
  28. }
  29. -(void)processCompleted {
  30. NSLog(@"Printing Process Completed");
  31. }
  32. @end
  33. int main(int argc, const char * argv[]) {
  34. NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
  35. SampleClass *sampleClass = [[SampleClass alloc]init];
  36. [sampleClass startAction];
  37. [pool drain];
  38. return 0;
  39. }

结果如下:

  1. 2022-07-07 21:15:50.362 Protocols[275:303] Printing Details
  2. 2022-07-07 21:15:50.364 Protocols[275:303] Printing Process Completed

在上面的实例中,我们看到了 delgate 方法是如何调用和执行的。它以 startAction 开始,一旦流程完成,将调用委托方法 processCompleted 以通知操作完成。

在任何 iOSMac 应用程序中,我们都不会在没有委托的情况下实现程序。因此,了解委托的用法非常重要。委托对象应使用 unsafe_unretained 属性类型以避免内存泄漏。