假设你有三个表格视图,分别用于狗、猫和鸟。点击每个单元格将显示一个新屏幕,其中包含它的放大照片。
为了设计这个功能,你需要为狗、猫和鸟设计三个不同的数据源。基本上你需要三个数组。
然而,你不需要三个表格视图代理。因为表格视图的行为都是相同的。它们只是呈现一个视图控制器,并用UIImage填充它。这只有在代理以通用方式编写时才成立,即代理中没有特定于狗、猫或鸟的代码。
话虽如此,你可以从数据源中抽象出狗、猫和鸟,但我的答案只是一个人为的例子。一些自定义对象太复杂,无法使用相同的结构,因此需要三个数据源。
旧答案:
在回答问题之前,你必须更好地理解委托设计模式:
让我先问一个问题:
默认情况下,TableView 是这样的:
![enter image description here](https://istack.dev59.com/cCipgl.webp)
UITableView如何知道要呈现多少个单元格?每个单元格中呈现什么?
- 它本身并不知道。
- 它会向另一个类询问,以便将单元格的数量和要返回的单元格(例如单元格图像、单元格标题、单元格子标题等)值通知给自己。通常情况下,您会在ViewController(代理类)中看到一个tableView(委托类)。
- 这种一个类询问另一个类的概念被称为委托!
现在您已经知道什么是委托,为了回答OP的实际问题:这主要涉及语义差异。
如果您只使用(而不是创建自己的协议)基础的代理和数据源,那么这对您来说并不重要。但是,如果您打算编写自定义协议,则了解它们将有助于更好地编写(以及更重要的是阅读、重构)代码。
从开发人员的角度来看,它们都处理委托类和代理类之间的交互。
数据源
一个数据源和代理几乎是相同的。不同之处在于与委托对象的关系。数据源被委派控制数据而非用户界面。委托对象通常是视图对象例如表视图,它持有对其数据源的引用并偶尔请求应显示的数据。数据源和委托一样必须采用协议并最少实现该协议的必需方法。数据源负责管理提供给委托视图的模型对象的内存。
通俗易懂的说:
数据源主要处理“什么”,通常在初始化时完成。委托主要处理“如何”,并向您提供一些参数以产生特定的行为,例如如果用户点击了这个…应该发生什么?如果他们滑动…应该发生什么?
以tableView为例:
数据源
它里面有什么?我正在呈现什么样的单元格?cellForRowAtIndexPath
。
章节的标题是什么?titleForHeaderInSection
。
有多少个单元格?numberOfRowsInSection
因此,通常你会返回值。对于代理来说,更常见的类型是void
。
数据源方法
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String?
委托方法
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
func tableView(tableView: UITableView, willBeginEditingRowAtIndexPath indexPath: NSIndexPath)
func tableView(tableView: UITableView, didEndEditingRowAtIndexPath indexPath: NSIndexPath)
我显然是有选择地进行了选择,因为有些数据源方法不返回,而有些委托方法确实会返回。
代理
在显示页脚后,我应该做什么/使用什么“行为形式”,您希望我弹出一个警告框吗?didEndDisplayingFooterView
我将拥有一种附加类型,可以为单元格提供一些额外的功能吗?accessoryTypeForRowWithIndexPath
NSEvent
)。一个对象可能会询问代理如何响应事件(无论是NSEvent
类型的事件还是其他对象的任何消息)。数据源在UI类之外并不常用,因为它们是不需要的;MVC模型是其自身的数据源。 - Barry Wark