我有一个与Cocoa框架设计模式相关的基本问题。
委托和数据源之间的区别是什么?
他们都可以使用@protocols
声明,但有些类或框架正在使用delegate
,而其他一些正在使用datasource
。
从UI/NSTableView
我可以理解的是delegate
响应与UI相关的事件,而datasource
与数据完全相关。但是,我不知道Cocoa的UI类之外的任何数据源实现。
注意:
答案 0 :(得分:42)
答案 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是这样的:
UITableView如何知道要呈现多少个单元格?在每个细胞中呈现什么?
现在你知道代表团是什么,回答OP的实际问题:
这主要是语义差异的巨大问题 如果您只是使用(而不是创建自己的协议)基金会的代表和数据源,那么它对您来说无关紧要。但是,如果您打算编写自定义协议,那么理解它们将有助于您更好地编写(并具有更高重要性的读取,折射器)代码。
从开发人员的角度来看,他们都处理了委托 - ing 类和委托类之间的交互。
数据源几乎与委托相同。区别在于 与委托对象的关系。而不是 委托控制用户界面,委派数据源 控制数据。委托对象,通常是视图对象 作为表视图,偶尔保存对其数据源的引用 询问它应显示的数据。数据源,如 代表,必须采用协议并至少实施所需的 该协议的方法。数据源负责管理 他们为委托视图提供的模型对象的内存。
以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先前所说:数据源提供数据,委托提供行为。