21

我真的对代表和协议的概念感到困惑。它们是否等同于 Java 中的接口和适配器类?它们是如何工作的?到目前为止,我读过的所有资源都没有帮助。“委托是一种简单而强大的模式,其中程序中的一个对象代表另一个对象或与另一个对象协调。委托对象保持对另一个对象(委托)的引用,并在适当的时间发送消息给它。” 我不知道这是什么意思。有人可以解释一下它们是什么并举一个简单的例子吗?提前致谢!

编辑:

据我现在了解,

1) 委托实现协议(接口的另一个名称)

2)对象注册一个委托(实现协议)

3) 对象可以在委托上调用协议方法

因此,委托将对象与协议连接起来。

如果我错了,请纠正我。

我还是不明白为什么对象本身不能实现协议?它本来可以容易得多!

4

3 回答 3

45

协议是一种指定一组方法的方法,如果它想与你的一个类一起工作,你希望一个类实现它。委托和数据源,如 UITableViewDelegate 和 UITableViewDataSource 确实是协议。

您可以通过以下方式指定协议:

@protocol MyProtocol <NSObject>

- (void)aRequiredMethod;

@required
- (void)anotherRequiredMethod;

@optional
- (void)anOptionalMethod;

@end

在 @required 之后或任何其他说明符之前声明的方法是必需的,并且想要使用您的协议的类需要实现所有这些方法。您还可以通过在 @optional 说明符之后声明一些可选方法来声明它们。

然后,您可以在类的接口中指定一个类“符合”协议(实现所需的方法):

@interface MyClass <MyProtocol>

@end

您通常使用属性保留对符合协议的对象的引用。例如,要跟踪委托:

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

此时,在您的代码中,您只需调用您要在您保留引用的对象上调用的方法,并像使用任何其他方法一样实现您的协议:

[self.delegate aRequiredMethod];

要检查对象是否符合协议,您可以调用

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

要检查对象是否实现了可以调用的方法

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

有关更多信息,请查看 Apple 的使用协议指南。

于 2013-06-19T13:32:17.603 回答
10

使用 声明的协议(@protocol syntax in Objective-C)用于声明“采用”(声明它将使用此协议)的类将实现的一组方法。这意味着您可以在代码中指定“只要它实现特定协议,您就不会关心使用哪个类”。这可以在 Objective-C 中完成,如下所示:

id<MyProtocol> instanceOfClassThatImplementsMyProtocol;

如果您在代码中声明了这一点,那么任何“符合”协议 MyProtocol 的类都可以在变量中使用instanceOfClassThatImplementsMyProtocol。这意味着使用这个变量的代码知道它可以使用 MyProtocol 中定义的任何方法和这个特定的变量,不管它是什么类。这是避免继承设计模式和避免紧耦合的好方法。

委托是对协议语言特性的一种使用。委托设计模式是一种设计代码以在必要时使用协议的方法。在 Cocoa 框架中,委托设计模式用于指定符合特定协议的类的实例。这个特定的协议指定了委托类应该实现的方法,以在给定的事件中执行特定的操作。使用委托的类知道它的委托符合协议,因此它知道它可以在给定的时间调用实现的方法。这种设计模式是解耦类的好方法,因为它使得将一个委托实例交换为另一个委托实例变得非常容易——程序员所要做的就是确保替换实例或类符合必要的协议(即

协议和委托不仅限于 Objective-C 和 Mac/iOS 开发,而且 Objective-C 语言和 Apple 框架大量使用了这种令人敬畏的语言特性和设计模式。

编辑:

请找到这个例子。在UIKit frameworkCocoa Touch 中,有一个UITextFieldDelegate协议。UITextField该协议定义了作为实例委托的类应实现的一系列方法。换句话说,如果你想将一个委托分配给一个UITextField(使用委托属性),你最好确保这个类符合UITextFieldDelegate. 其实是因为delegate的属性UITextField定义为:

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

然后,如果您为其分配一个未实现协议的类,编译器将发出警告。这真的很有用。你必须声明一个类实现了一个协议,并且说它实现了,你让其他类知道他们可以以特定的方式与你的类交互。因此,如果您将 的实例分配MyTextFieldDelegateClass给 的委托属性UITextField,则UITextField知道它可以调用您的某些特定方法(与文本输入、选择等相关)MyTextFieldDelegateClass。它知道这一点,因为MyTextFieldDelegateClass已经说过它将实现该UITextFieldDelegate协议。

最终,这一切都会为您的项目代码带来更大的灵活性和适应性,我相信您在使用这项技术后很快就会意识到这一点!:)

于 2013-06-19T13:27:32.980 回答
9

在最简单的形式中,委托是一个从另一个对象接收消息的对象。而你一直这样做。

所以说你有一个带引擎的汽车对象。

@interface car : NSObject

@property (nonatomic) id engine;

@end

因此可以将启动消息转发给引擎。

[_engine start];

引擎充当代表,您只是向它传递消息。

协议使它更正式,Xcode 将检查您是否符合必需或可选的方法。

@property (nonatomic) id <engineDelegate> engine;

表示引擎对象必须包含函数 start 因为在协议定义中它要求它。

@protocol engineDelegate 
 - (void) start;
@optional
 - (double) fuelLevel;
@end

为什么代表和协议如此酷?好吧,因为引擎可以是您可以在运行时使用的任意数量的不同引擎,它可以是喷气发动机、内燃机、相位调制发动机,只要它符合协议,它就没有关系。然后你告诉 Xcode 它确实符合通过将委托添加到类接口。

@interface timeWarpDrive : NSObject <engineDelegate>
于 2014-05-28T03:37:14.927 回答