【问题标题】:What exactly are protocols and delegates and how are they used in IOS?协议和委托到底是什么,它们在 IOS 中是如何使用的?
【发布时间】:2013-06-19 13:18:18
【问题描述】:

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

编辑:

据我所知,

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

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

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

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

如果我错了,请纠正我。

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

【问题讨论】:

  • 你读过哪些文章,你发现哪些例子你想不通?
  • 不,委托不像接口。
  • 协议就像 Java 中的接口。它们是 Objective-C 语言的一个具体特征。然而,委托是连接到其他对象的对象,并在“其他对象”的状态发生变化时发送消息。它们只是一个模式。
  • Totumus Maximus: developer.apple.com/library/ios/#documentation/general/… iosdevelopertips.com/objective-c/… 无法弄清楚代表是什么以及协议是什么。如果你花时间回答一个问题,至少要明智地利用这段时间,真正回答一个问题,而不是问另一个问题。
  • ole_92。当一个对象不能单独完成一项工作或只想允许其他方参与该事件时,它就声明了一个协议。例如,如果 UITableView 没有要求它的数据源或委托来提供某些信息或响应某些用户交互,那么它就不可能是灵活的类。

标签: ios delegates protocols


【解决方案1】:

协议是一种指定一组方法的方法,如果它想与你的一个类一起工作,你希望一个类实现它。委托和数据源,如 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

【讨论】:

  • 您好,感谢您的回答!所以,关于这句话:“像 UITableViewDelegate 和 UITableViewDataSource 这样的委托和数据源确实是协议。”代表是一种协议? “您通常使用属性来保持对符合协议的对象的引用。例如,要跟踪委托:”那么,委托是对实现协议的对象的引用?
  • 不客气。代表并不是一种真正的协议。他们之所以这样称呼,是因为他们通常会询问完成任务所需的信息。例如。 UITableViewDataSource 询问 UITableView 显示数据所需的所有信息(numberOfCells、numberOfSections 等)。相反,委托协议之所以这样称呼,是因为它通常会响应委托给他们的操作。例如,UITableViewDelegate 以这种方式将用户点击单元格等事件委托给 viewController。
  • 我在之前的评论中没有留下任何空间......但是......是的,我使用“委托”来表示实现协议的对象。
【解决方案2】:

使用(@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的delegate属性定义为:

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

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

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

【讨论】:

  • 加一为努力。
【解决方案3】:

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

假设你有一个带引擎的汽车对象。

@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>

【讨论】:

  • 如果您通过显示每个文件的文件名/完整代码示例来详细说明您的代码示例,此答案对初学者会更有帮助。
猜你喜欢
  • 1970-01-01
  • 2021-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多