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

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

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

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

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

Примечание:

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

Ответы

Ответ 1

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

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

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

Ответ 2

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

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

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

Ответ 3

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

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

enter image description here

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

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

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

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

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

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

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

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

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

Ответ 4

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

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

Ответ 5

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

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

общие методы: willSelectRow, didSelectRow, willDisplay, heightForRow, willBeginEditingAt

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

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

Ответ 6

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