协议和委托之间有什么区别?

61

一个 protocol 和一个 delegate 的区别是什么?

另外,

我们如何在 protocol类 中声明 变量

7个回答

84

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

id<MyProtocol> instanceOfClassThatImplementsMyProtocol;

如果在代码中声明了此内容,则任何符合协议MyProtocol的类都可以在变量instanceOfClassThatImplementsMyProtocol中使用。这意味着使用此变量的代码知道它可以使用MyProtocol中定义的任何方法,而不管它是什么类。这是避免继承设计模式的好方法,并避免紧密耦合。

委托是协议语言特性的一种使用方式。委托设计模式是一种设计代码以在必要时使用协议的方法。在Cocoa框架中,委托设计模式用于指定符合特定协议的类的实例。这个特定协议指定了委托类应该实现以在给定事件中执行特定操作的方法。使用委托的类知道它的委托符合协议,因此它知道可以在给定时间调用已实现的方法。这种设计模式是解耦类的好方法,因为它使得很容易将一个委托实例替换为另一个 - 程序员所要做的就是确保替换实例或类符合必要的协议(即它实现了协议中指定的方法)!
协议和委托不仅限于Objective-C和Mac/iOS开发,但Objective-C语言和苹果框架大量使用这个强大的语言特性和设计模式。
编辑:
这里有一个例子。在Cocoa Touch的UIKit框架中,有一个UITextFieldDelegate协议。这个协议定义了一系列方法,委托UITextField实例的类应该实现这些方法。换句话说,如果你想给UITextField分配一个委托(使用delegate属性),你最好确保这个类符合UITextFieldDelegate。实际上,因为UITextField的delegate属性被定义为:
@property(nonatomic, weak) id delegate 然后,如果您将一个没有实现协议的类分配给它,编译器会发出警告。这非常有用。您必须声明一个类实现了一个协议,并在声明它时,让其他类知道它们可以以特定的方式与您的类交互。因此,如果您将MyTextFieldDelegateClass的实例分配给UITextField的delegate属性,UITextField就知道它可以调用您的MyTextFieldDelegateClass的一些特定方法(与文本输入、选择等相关)。它之所以知道这一点,是因为MyTextFieldDelegateClass已经说过它将实现UITextFieldDelegate协议。
最终,这一切都会导致您的项目代码具有更大的灵活性和适应性,我相信在使用这项技术后,您很快就会意识到这一点! :)

3
协议是你要做什么,委托是如何去做? - 3lvis
13
我不确定我完全理解你的意思。委托是一种设计模式,它允许一个类以一种使代码解耦的方式从另一个类那里承担某些责任(非常好、灵活的事情)。协议是Objective-C语言的一个特性,它允许你编写和使用利用委托概念的代码。 - James Bedford
@JamesBedford,你能告诉我"id<MyProtocol>"的意思是什么吗? - Exploring
1
当然可以!"id" 是一种表示指向任何对象的指针类型,而"id<MyProtocol>"是一种表示指向实现了MyProtocol协议的任何对象的指针类型。 - James Bedford
1
如果不将assign修改为weak,一旦委托被释放并在未来访问时,程序就会崩溃。 - Genki
显示剩余2条评论

36

协议是一组方法(可选或必需的),将由符合该协议的类实现。而委托是指向符合该协议的类的引用,并将遵守实现协议中定义的方法。

请参阅此 Apple 文档以获取更多详细信息。


14

代理模式:

它是一种设计模式,其中一个名为代理的对象代表另一个对象并应其请求行事。在执行的某个点上,它向其代理发送消息;该消息告诉代理某些事件即将发生,并请求某些响应。代理实现由消息调用的方法并返回适当的值。

一个例子就是appdelegate对象代表appobject行事。

协议:

协议是声明编程接口的程序界面,任何类都可以实现其方法。协议是objective c 语言特性。简单来说,它是一个类可以实现的方法列表。要使用它,您需要确认该协议。例如UITableviewDatasource协议,其中的cellforRowAtIndexPath方法在协议中声明,但我们为创建表视图而实现它。

参考https://developer.apple.com/library/mac/referencelibrary/GettingStarted/RoadMapOSX/books/StreamlineYourAppswithDesignPatterns/StreamlineYourApps/StreamlineYourApps.html


11
我们可以将协议定义为一组规则。 这些规则可以是可选的或必需的,就像我们在协议中使用的那样。 代理是Objective-C和Swift中的一种消息传递技术。对象必须处理该消息。
例如:每个iOS开发人员都要使用UITableview,当创建表时,您必须在控制器中实现cellForRowAtIndexPath()numberOfRowsInSection(),这些规则(协议)被定义为UItableview类中的必要协议。 还有其他的协议,如heightForRowAtIndexPath()是可选的。
现在来看UITableView中的Delegate,其中有一个消息didSelectRowAtIndexPath(),它会向您发送一个事件的消息。 如果您将代理设置为self,则表示您的控制器已准备好处理该事件。
对于开发人员来说,这些术语似乎更加令人困惑,因为我们习惯于将它们一起使用。
祝愉快!

这绝对是最简单的解释。 - novice

7
一个重要的前提是先了解协议,然后再了解委托。我建议您先查看this简短的教程,然后查看什么是协议?。此外,您必须知道类和协议之间的区别,因此请参见Objective-C:类与协议协议的意义是什么?

协议(protocol)只是一组需要实现的函数的蓝图。任何采纳该蓝图的类都将必须实现这些函数。(不要将实现函数与调用函数混淆)

代理(delegate)1让你能够在不使用继承的情况下执行委托类所做的事情,例如:

例如,您有一个视图控制器,想要下载图片或者获取客户到店铺的距离,而不是自己完成所有这些工作,您可以使用一个中介对象来帮您完成。该对象被称为代理对象。通常,您会这样做:

class ViewController : UIViewController , DownloaderDelegate{
//other code

// inside viewDidLoad or elsewhere you write:
downloaderHandler.delegate = self // now self can also use whatever the delegating object gives it...previously it was only a viewController but now it's 'almost' also a downloader

非常类似于符合tableViewDelegate的操作。
class ViewController : UIViewController , UITableViewDelegate{
//other code

// inside viewDidLoad or elsewhere you write
tableView.delegate = self 

现在您的self也可以执行与tableView相关的操作。


delegate:2

但是这个对象(代理)是一个普通的对象(id或Any)。它很笨!你需要告诉它:“嘿,为了让你拥有特定的功能,你需要符合我们为你定义的协议。(我们不会扩展Any或id,因为那样太愚蠢了,相反地,我们制定了一个非常明确的限定协议)”
在Objective-C中,它是一个纯的vanilla id,所以你要这样做。
 @property (weak) id<DownloaderProtocol>delegate;  

在Swift中,稍微容易一些,你可以这样做:
weak var delegate:DownloaderProtocol?

协议来拯救...代理实现(而不是使用)该函数以适应委托类的需求。


在Swift中,你没有id类型,但是你也不需要它的等效类型Any,因为在Swift中协议也是一种第一类公民类型。

4

让我们来看一下程序中委托的声明

 id<myProtocol> *delegatingObject;

delegatingObject 保持对其他对象的引用,并在适当的时候向该对象发送消息。

协议是一组相关的属性和方法,可以由任何类来实现。

这意味着任何确认 myProtocol(一组相关的属性和方法)的对象(id 类型)都可以作为代理工作,或者您可以说任何拥有所需学位的人(id)都可以作为教师(delegate)工作。


0

Delegate和Protocol属于视图控制器或类之间的(一对一)通信模式概念。

这意味着一个类或视图控制器正在与另一个类或视图控制器进行交流(记住一对一通信)。

第一个类或视图控制器通过确认第二个类的协议,将其引用(委托)给它正在交流的第二个类。

使用第一个类的引用,第二个类代表第一个类完成工作,并因此向第一个类提供信息。

请通过以下链接观看实现该概念的视频: https://www.youtube.com/watch?v=DBWu6TnhLeY

正式解释是- Protocol是一组方法(可选或必需),由确认该协议的(第一)类实现。而delegate是指确认该协议的(第一)类的引用,并将遵守实现协议中定义的方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接