В чем разница между источником данных и делегатом? - PullRequest
40 голосов
/ 09 февраля 2010

У меня есть фундаментальный вопрос, связанный с шаблонами проектирования фреймворков Cocoa.

В чем разница между делегатом и источником данных?

Оба могут использовать объявление @protocols, но некоторые классы или платформы используют delegate, а некоторые другие * datasource.

Все, что я могу понять из UI/NSTableView, - это delegate ответ на события, связанные с пользовательским интерфейсом, в то время как datasource просто связан с данными. Но я не знаю каких-либо реализаций источника данных за пределами UI-классов Cocoa.

Примечание:

  • Делегат, которого я упомянул в этом вопросе, не всегда связан с событиями пользовательского интерфейса.
  • Ответ на вопрос источника данных.

Ответы [ 6 ]

43 голосов
/ 09 февраля 2010

Источник данных предоставляет данные, а делегат - поведение.

В MVC источник данных находится на уровне модели, а делегат - на уровне управления.

На самом деле, если подумать, источником данных обычно является контроллер, который находится ниже, ближе к модели. Я не думаю, что когда-либо использовал модельный объект в качестве источника данных.

32 голосов
/ 10 февраля 2010

Шаблоны делегатов и источников данных в значительной степени независимы и ортогональны:

Шаблон делегата очень распространен в Какао и позволяет делегату (любому экземпляру, реализующему неофициальный протокол делегата до OS X 10.6, или формальному делегату @protocol в 10.6 и позже) изменять поведение экземпляра объекта. Этот шаблон часто используется вместо создания подклассов: вместо того, чтобы создавать классы для изменения его поведения, вы предоставляете делегат, который отвечает на соответствующие методы. Классы, использующие делегатов, отправляют сообщения своим делегатам по контрактным событиям. API между классом и делегатом определяется классом и отличается для каждого класса, который использует шаблон, но API обычно состоит из сообщений, спрашивающих делегата, как обрабатывать определенное событие. Одно из преимуществ шаблона делегирования над подклассами заключается в том, что класс может реализовывать несколько протоколов делегирования, позволяя его экземплярам выступать в качестве делегата для нескольких классов. Точно так же экземпляр объекта может быть делегатом для нескольких других объектов (следовательно, большинство API делегатов передают объект в качестве первого аргумента каждому сообщению в API). Шаблон делегата не так распространен в других инфраструктурах пользовательского интерфейса (хотя Qt использует шаблон делегата в своей структуре Model / View) и не так же, как делегаты .Net / CLR, которые по существу являются типизированными указателями функций. .

Шаблон источника данных часто используется подклассами NSView в Какао, которые имеют сложные данные состояния, такие как NSBrowser, NSTableView, NSOutlineView и т. Д. Протокол источника данных определяет API, который экземпляры этих (и других) классов может использовать для получения данных для отображения в представлении. Хотя архитектуры NSController и Cocoa Bindings заменили многие способы использования шаблона источника данных, он все еще распространен и очень эффективен. Как и шаблон делегата, описанный выше, часть его возможностей исходит от объекта, способного выступать в качестве источника данных для нескольких экземпляров, использующих источник данных (и, возможно, даже экземпляров нескольких классов, которые имеют разные протоколы источника данных). Шаблон источника данных обычно используется в других инфраструктурах пользовательского интерфейса, таких как Qt (в структуре Модель / Представление, где модель аналогична источнику данных) и WPF / Silverlight (где источник данных может быть более близок к модели представления. ).

12 голосов
/ 21 мая 2016

Прежде чем ответить на вопрос, вы должны лучше понять шаблон проектирования делегирования: Позвольте мне начать с вопроса:

По умолчанию TableView выглядит так:

enter image description here

Как UITableView знает, сколько ячеек представить? что подарить в каждую клетку?

  • Сам по себе, он не знает.
  • Он просит другой класс сообщить его о количестве ячеек и о том, какую ячейку вернуть (какие cellimage, celltitle, cellubtitle и т. Обычно вы видите tableView (делегирующий класс) внутри ViewController (делегирующий класс)
  • Эта концепция, когда один класс задает другой, называется делегированием!

Теперь, когда вы знаете, что такое делегация, чтобы ответить на актуальный вопрос ФП:

Это в основном ОГРОМНЫЙ вопрос семантических различий.
Если вам нужно использовать (а не создавать собственный протокол) делегатов и источники данных фонда, то это действительно не имеет значения для вас. Однако, если вы намереваетесь писать собственные протоколы, то понимание их поможет вам лучше написать (и с более важным чтением, рефрактором) код.

С точки зрения разработчика, они оба имеют дело с взаимодействием между классом делегата ing и классом делегата.

Источник данных

Источник данных практически идентичен делегату. Разница в отношения с делегирующим объектом. Вместо того, чтобы делегированное управление пользовательским интерфейсом, источник данных делегирован контроль данных. Делегирующий объект, обычно объект вида, такой как табличное представление, содержит ссылку на свой источник данных и иногда запрашивает данные для отображения. Источник данных, как делегат, должен принять протокол и реализовать как минимум методы этого протокола. Источники данных отвечают за управление память объектов модели, которые они передают в делегирующее представление.

С точки зрения непрофессионала:

DataSource в основном имеет дело с чем и обычно делает это при инициализации . Делегат имеет дело главным образом с как и передает вам некоторые параметры, чтобы дать определенное поведение, например, если пользователь нажал на это ... что должно произойти? если они сильно ударили ... что должно произойти?

В качестве примера для tableView:

DataSource
Что у него внутри? Какую клетку я представляю? 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

8 голосов
/ 22 мая 2012

С моей точки зрения, DataSource - это объект, который не знает, где находятся данные, и поэтому вы должны его предоставить. Например, сообщая объекту, сколько элементов в столбце.

A Delegate, который является частью, которую объект показывает вам, должен быть реализован вашим классом, потому что объект знает, где находятся данные, но не знает, как их правильно использовать.

3 голосов
/ 03 июня 2018

Чтобы сделать его коротким:

Делегат относится к пользовательскому интерфейсу и действиям пользователя над ячейками и таблицей.

распространенные методы: willSelectRow, didSelectRow, willDisplay, heightForRow, willBeginEditingAt

Источник данных занимается редактированием, заполнением и отображением данных на за столом.

общие методы canEditRowAt, commit, titleForHeaderInSection, cellForRowAt, numberOfSections, sectionIndexTitles

0 голосов
/ 07 апреля 2019

И то, и другое Протокол , теперь основная цель Протокол состоит в том, чтобы придерживаться универсальной практики кодирования или одинаковой практики кодирования для всех (насколько я понимаю). Предположим, что я создаю tableView без UITableViewDataSource & UITableViewDelegate , я бы создал tableView таким образом, чтобы вы этого не делали. Вот где приходит Protocol , Apple создала некоторый набор правил или protocol , и каждый должен следовать этому. Теперь DataSource & Делегат , очевидно, Protocol , видя имя, которое вы можете понять DataSource имеет дело с чем-то вроде numberOfRowsInSection, cellForRowAtIndexPath , numberOfSections tableView, где некоторые виды данных принимаются / обрабатываются, и Делегаты являются didSelectRow , willSelectRow , heightForRow и т. Д. TableView, где это связано с каким-либо изменением / действием пользовательского интерфейса. Так что в соглашении об именах нет ничего гипотетического, чтобы разделить задачу. Как сказал @kubi ранее: источник данных предоставляет данные, а делегат - поведение.

...