协议和代表究竟是什么以及它们在IOS中的使用方式?

时间:2013-06-19 13:18:19

标签: ios delegates protocols

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

编辑:

据我所知,

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

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

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

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

如果我错了,请纠正我。

我仍然不明白为什么对象本身无法实现协议?它可能会变得如此简单!

3 个答案:

答案 0 :(得分:44)

协议是一种指定一组希望类实现的方法的方法,如果它想要使用其中一个类。像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的指南Working With Protocols

答案 1 :(得分:10)

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

id<MyProtocol> instanceOfClassThatImplementsMyProtocol;

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

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

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

编辑:

请找到此示例。在Cocoa Touch的UIKit framework中,有一个UITextFieldDelegate协议。该协议定义了一系列方法,这些方法应该实现UITextField实例的委托。换句话说,如果要将委托分配给UITextField(使用委托属性),则最好确保此类符合UITextFieldDelegate。实际上,因为UITextField的委托属性定义为:

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

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

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

答案 2 :(得分: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>