数据源和委托之间有什么区别?

时间:2010-02-09 20:01:19

标签: cocoa delegates protocols datasource

我有一个与Cocoa框架设计模式相关的基本问题。

委托和数据源之间的区别是什么?

他们都可以使用@protocols声明,但有些类或框架正在使用delegate,而其他一些正在使用datasource

UI/NSTableView我可以理解的是delegate响应与UI相关的事件,而datasource与数据完全相关。但是,我不知道Cocoa的UI类之外的任何数据源实现。

注意:

  • 我在这个问题中提到的代表并不总是与UI事件有关。
  • 数据来源问题已得到解答。

6 个答案:

答案 0 :(得分:42)

数据源提供数据,委托提供行为。

MVC中,数据源位于模型层中,委托位于控制层中。

实际上,在第二个想法中,数据源通常是较低的控制器,更靠近模型。我不认为我曾经使用过模型对象作为我的数据源。

答案 1 :(得分:32)

委托和数据源模式在很大程度上是独立的,而且是正交的:

委托模式在Cocoa中非常常见,并且允许委托(在OS X 10.6之前实现非正式委托协议的任何实例,或在10.6及更高版本中实现正式委托@protocol来修改对象的行为)实例。通常使用此模式而不是子类化:代替子类化以更改其行为,您提供响应适当方法的委托。使用委托的类在签约事件中向其委托发送消息。类和委托之间的API由类定义,并且对于使用该模式的每个类是不同的,但API通常由询问委托如何处理特定事件的消息组成。委托模式优于子类化的一个优点是类可以实现多个委托协议,允许其实例充当多个类的委托。类似地,对象实例可以是多个其他对象的委托(因此大多数委托API将对象作为API中每个消息的第一个参数传递)。委托模式在其他UI框架中并不常见(虽然Qt确实在其Model / View框架中使用委托模式),并且与.Net / CLR委托相同,它们本质上是类型化的函数指针。

数据源模式通常由Cocoa中具有复杂状态数据的NSView子类使用,例如NSBrowser,NSTableView,NSOutlineView等。数据源协议定义了这些实例的API(和其他)类可用于获取要在视图中显示的数据。虽然NSController和Cocoa Bindings架构已经取代了数据源模式的许多用途,但它仍然很常见且非常强大。与上面描述的委托模式一样,它的一部分功能来自一个对象,它可以作为多个数据源使用实例的数据源(甚至可能是具有不同数据源协议的多个类的实例)。数据源模式通常用于其他UI框架,例如Qt(在Model / View框架中,模型类似于数据源)和WPF / Silverlight(其中数据源可能更类似于视图模型) )。

答案 2 :(得分:12)

在回答问题之前,您必须更好地了解委托设计模式: 我先来问一个问题:

默认情况下,TableView是这样的:

enter image description here

UITableView如何知道要呈现多少个单元格?在每个细胞中呈现什么?

  • 本身,它不知道。
  • 它要求另一个类告知它关于单元格的数量以及要返回的单元格(cellimage,celltitle,cellsubtitle等)对自身的值。您通常会在ViewController(委托类)
  • 中看到tableView(委托类)
  • 这个一个类的概念要求另一个被称为委托!

现在你知道代表团是什么,回答OP的实际问题:

这主要是语义差异的巨大问题 如果您只是使用(而不是创建自己的协议)基金会的代表和数据源,那么它对您来说无关紧要。但是,如果您打算编写自定义协议,那么理解它们将有助于您更好地编写(并具有更高重要性的读取,折射器)代码。

从开发人员的角度来看,他们都处理了委托 - ing 类和委托类之间的交互。

Data Source

  

数据源几乎与委托相同。区别在于   与委托对象的关系。而不是   委托控制用户界面,委派数据源   控制数据。委托对象,通常是视图对象   作为表视图,偶尔保存对其数据源的引用   询问它应显示的数据。数据源,如   代表,必须采用协议并至少实施所需的   该协议的方法。数据源负责管理   他们为委托视图提供的模型对象的内存。

以Layman的名义:

DataSource主要处理内容,通常在初始化时执行的内容。 委托交易主要使用如何提供您的某些参数来提供某种行为,即如果用户点击了这个......会发生什么?如果他们刷了......会发生什么?

作为tableView的一个例子:

<强>数据源
里面有什么?我呈现什么样的细胞? cellForRowAtIndexPath
科的标题是什么? titleForHeaderInSection 他们有多少个细胞? numberOfRowsInSection 因此,您通常返回值。对于代表来说,void类型更为常见。

数据源方法

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell // return a cell ie UITableViewCell
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int // return a number ie an Int
func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? // return the title ie a String  

委派方法

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
func tableView(tableView: UITableView, willBeginEditingRowAtIndexPath indexPath: NSIndexPath)
func tableView(tableView: UITableView, willBeginEditingRowAtIndexPath indexPath: NSIndexPath)

我显然选择性地选择了一些数据源方法不返回,一些委托方法返回

<强>代表
在完成页脚显示后,我应该怎么做/应该采用什么样的行为?你想让我发出警报吗?didEndDisplayingFooterView

我是否会使用为游戏提供额外功能的accessoryType? accessoryTypeForRowWithIndexPath

答案 3 :(得分:8)

从我的角度来看,DataSource是一个不知道数据位置的对象,因此你应该提供它。比如告诉对象列中有多少项。

Delegate是对象向您展示的一部分,必须由您的类实现,因为该对象知道数据的位置,但它不知道如何正确使用它。

答案 4 :(得分:3)

简而言之:

委托与针对单元格和表格的UI和用户操作有关。

常用方法:willSelectRow,didSelectRow,willDisplay,heightForRow,willBeginEditingAt

数据源处理数据的编辑,填充和显示 tableview。

常用方法canEditRowAt,commit,titleForHeaderInSection,cellForRowAt,numberOfSections,sectionIndexTitles

答案 5 :(得分:0)

这两个都是协议,现在协议的主要意图是保持通用编码实践,或者对所有人保持相同的编码实践(据我所知)。假设我要创建一个没有 UITableViewDataSource UITableViewDelegate 的tableView,那么我将创建tableView,而您不会这样做。正是协议出现的地方,苹果公司创建了一套规则或 Protocol ,每个人都必须遵守。现在 DataSource Delegate 显然是协议,看到您可以理解的名称 DataSource 处理的是 tableOf的numberOfRowsInSection cellForRowAtIndexPath numberOfSections 代表 didSelectRow willSelectRow heightForRow 等,它与某种类型的UI更改/操作相关。因此,只是命名约定而已,没有任何假想将任务分开。正如@kubi先前所说:数据源提供数据,委托提供行为。