【问题标题】:What's the difference between data source and delegate?数据源和委托有什么区别?
【发布时间】:2011-01-14 23:39:18
【问题描述】:

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

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

它们都可以使用@protocols 声明,但一些类或框架使用delegate,而另一些使用datasource

我从UI/NSTableView 所能理解的只是delegate 响应与UI 相关的事件,而datasource 则纯粹与数据相关。但是,我不知道 Cocoa 的 UI 类之外的任何数据源实现。

注意:

  • 我在这个问题中提到的委托并不总是与 UI 事件相关。
  • 已回答数据源问题。

【问题讨论】:

    标签: cocoa delegates protocols datasource


    【解决方案1】:

    假设您有 3 个表格视图。适用于狗、猫和鸟。点击每个单元格将显示一个带有放大照片的新屏幕。

    要设计这个,您需要为狗、猫和鸟提供 3 个独立的数据源。你基本上需要三个数组。

    但是,您不需要 3 个 tableview 代表。因为表格视图的行为都是一样的。他们都只是呈现一个 viewController 并用 UIImage 填充它。仅当您的委托以通用方式编写时才适用,即委托中没有特定于狗、猫或鸟的代码。

    话虽如此,您可以从数据源中抽象出狗、猫、鸟,但我的回答只是一个人为的例子。一些自定义对象过于复杂,无法使用相同的结构,因此需要有 3 个数据源。

    旧答案:

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

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

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

    • 它自己不知道。
    • 它要求另一个类通知它自己的单元格数量和返回什么单元格(什么单元格图像、单元格标题、单元格子标题等)值。您通常会在 ViewController(委托类)中看到一个 tableView(委托类)
    • 一个班级要求另一个班级的这种概念称为委托!

    现在您知道什么是委托,回答 OP 的实际问题:

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

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

    Data Source

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

    通俗地说:

    DataSource 主要处理什么,并且通常是在初始化时。 代表主要处理如何feeds你一些参数来给出某种行为,即如果用户点击这个......会发生什么?如果他们刷卡了……会发生什么?

    以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, didEndEditingRowAtIndexPath indexPath: NSIndexPath)
    

    我显然是有选择地选择了一些数据源方法不返回而一些委托方法确实返回


    委托
    完成页脚显示后我应该做什么/应该使用什么“行为形式”,你想让我弹出警报吗?didEndDisplayingFooterView

    我是否要使用为单元格提供一些额外功能的附件类型? accessoryTypeForRowWithIndexPath

    【讨论】:

      【解决方案2】:

      两者都是Protocol,现在Protocol的主要意图是保持通用的编码实践,或者所有人的相同编码实践(据我所知)。假设我正在创建一个没有 UITableViewDataSourceUITableViewDelegate 的 tableView,我会以你不会的方式创建 tableView。这就是 Protocol 的来源,Apple 创建了一些规​​则或 protocol,每个人都必须遵循。现在 DataSourceDelegate 显然是 Protocol,看到你可以理解的名称 DataSource 处理类似于 tableView 的 numberOfRowsInSectioncellForRowAtIndexPathnumberOfSections,其中正在获取/处理某种数据,DelegatesdidSelectRow willSelectRowheightForRow 等 tableView 与某种 UI 更改/操作相关。因此,它只是命名约定,没有任何假设可以将任务分开。正如@kubi 之前所说:数据源提供数据,委托提供行为。

      【讨论】:

        【解决方案3】:

        简而言之:

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

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

        数据源处理数据的编辑、填充和显示 表格视图。

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

        【讨论】:

        • **欲了解更多详细信息,只需查看文档,您就会清楚地看到它们的区别。
        【解决方案4】:

        在我看来,DataSource 是一个不知道数据在哪里的对象,因此您应该提供它。比如告诉一个对象一列有多少项。

        Delegate,这是对象向您显示的部分,必须由您的类实现,因为对象知道数据在哪里,但它不知道如何正确使用它。

        【讨论】:

          【解决方案5】:

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

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

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

          【讨论】:

          • 好了,很全面的解释。我现在的理解是数据源不响应事件。在 Cocoa 类的情况下,它只提供了一种方法来实现在某个视图中显示哪些数据。我只是不确定为什么数据源的概念从未在与 UI 相关的 Cocoa 框架类之外使用。
          • @Jesse 需要明确的是,委托和数据源都不会直接响应 UI 事件(即通过运行循环传递给应用程序的 NSEvent)。对象可能会询问委托如何响应事件(NSEvent 类型的事件或来自其他对象的任何其他消息)。数据源不在 UI 类之外使用,因为它们不是必需的; MVC 的模型是它自己的数据源。
          • 好的,如果您误解了,请见谅。我并不是说委托总是响应 UI 事件。我主要关心的是在 UI 类之外使用的术语数据源的“灵活性”。我同意,而且我从来没有发现任何外部 UI 类的需要。
          • 你使用的语言非常难。我想只有经历过的人才能理解。
          【解决方案6】:

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

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

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

          【讨论】:

            猜你喜欢
            • 2011-07-16
            • 2011-10-12
            • 1970-01-01
            • 2010-09-09
            • 2011-10-30
            • 2010-12-13
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多