Какая разница между источником данных и делегатом?
У меня есть фундаментальный вопрос, связанный с шаблонами проектирования 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 выглядит так:
Как 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 ранее: источник данных предоставляет данные, а делегат - поведение.