Pull to refresh

Comments 11

Я не понимаю людей, которые плюсуют такие статьи. Это просто шок контент.

Мало того, что половина статьи вообще не имеет ни малейшего отношения к делегатам, так и сам делегат сделан неправильно!

Меня неимоверно огорчают статьи на тему iOS. На мой взгляд, в 99% сталкиваешься с просто вопиющей неграмотностью, которую я могу объяснить лишь полнейшим непониманием пределов собственного познания. Что ещё хуже обычной некомпетентности.

  • Код картинками. Ну это ладно;

  • Слишком большой фокус на удалении сториборда. Чёрт бы с ним, статья вообще не об этом, пусть бы был сториборд. Но это тоже ладно;

  • Не критика, но если уж хочется сделать тестовый экран с какой-то кнопкой, я всегда делаю rightBarButtonItem с одним из системных "стилей". Не нужно делать никакого лейаута, никаких пропертей, не нужно даже заголовок придумывать;

  • Всё началось с newtextForLabel. Как это вообще? Я понимаю, что это "мелочи", но мне это уже о многом говорит. Почему "text" не с большой буквы, хотя всё остальное в camelCase?;

  • ViewControllerDelegate. Это тоже для меня признак полнейшего непонимания темы. По-моему, по всем признакам это должно было называться SecondViewControllerDelegate;

  • "Когда мы закрываем SecondViewController, смахивая его вниз, срабатывает метод deinit. В нашем примере это отличное место, чтобы передать новый текст в лейбл." – я многое видел, но такого я ещё не видел. Это как минимум просто неверное допущение – надеяться на то, что при "закрытии" UIViewController он обязательно будет деаллоцирован;

  • метод делегата мало того, что имеет нелепый нейминг (не сообщает о случившемся событии, не спрашивает никаких данных), так и не имеет первым аргументом объекта, пославшего событие. В Delegates and Data Sources есть пример того, как стоит оформлять подобные методы (раздел "The Form of Delegation Messages");

Кошмар, просто кошмар. Я всё чаще начинаю сам себя презирать за то, что продолжаю заниматься разработкой под iOS, потому что уже просто стыдно находиться в таком сообществе. На свой личный счёт это принимать не стоит, но раньше писатели статей хотя бы одну книжку прочитывали перед тем, как что-то опубликовать. Теперь как будто бы и этого не происходит.

... и если 10 лет назад не было толком никаких хороших ресурсов, мало где было что-то почитать, меньше было разработчиков под iOS – то сегодня же всё совсем не так. Уже каждая собака имеет блог на медиуме, есть множество обучающих видео (я уж не говорю о WWDC Sessions), и в принципе не такая проблема найти живого человека, чтобы учиться от него.

Как при всём этом изобилии контента получаются статьи вроде вот этой? Моя чаша переполнена, я раньше просто проходил мимо, теперь же я буду просто уничтожать такие статьи.

Можете объяснить чем делегаты принципиально отличаются от каллбеков?

Паттерн делегатов также активно используется в c#. Но в java каллбеки.

Мне казалось что по факту - это одно и то же;)

Делегаты от коллбеков отличаются принципиально.

Но если серьёзно, то мне было очень сложно ответить на этот вопрос, не получалось сформулировать не то что чёткую разницу, а даже строгие определения обоих терминов.

Существует такое определение для Delegation Pattern:

In delegation, an object handles a request by delegating to a second object (the delegate). The delegate is a helper object, but with the original context. With language-level support for delegation, this is done implicitly by having self in the delegate refer to the original (sending) object, not the delegate (receiving object).

Я не был уверен, является ли передача "sender" первым аргументом неотъемлемым атрибутом делегирования, но, судя по всему, является.

Определение "коллбека" для меня было ещё более размытым. Можно подумать о коллбек-функциях и коллбек-замыканиях. Коллбек-функции (если это standalone функции), с одной стороны, не захватывают никакого контекста. С другой стороны, в коллбек-функцию всё равно всегда хочется передать какой-нибудь void *context, чтобы внутри функции можно было принимать какие-то решения в runtime.

Другой реализацией коллбека (особенно в iOS разработке сегодняшнего дня) скорее будет Objective-C Block или Swift Closure. И мы, как правило, захватываем весь нужный нам контекст самостоятельно как сильную ссылку или копию примитива, но ничто не мешает передавать нужные данные в аргументах. Поэтому сигнатура может быть точно такой же как и у методов делегата, ровно как и семантика использования.

Если прочитать определение для "callback" на Википедии, то там говорится следующее:

a callback or callback function is any reference to executable code that is passed as an argument to another piece of code; that code is expected to call back (execute) the callback function as part of its job. This execution may be immediate as in a synchronous callback, or it might happen at a later point in time as in an asynchronous callback.

В целом, я согласен с этим определением. Но тогда я для себя делаю вывод, что коллбек(и) в некоторых ситуациях являются частным случаем Delegate Pattern. Т.е. могут являться одним из способов реализации. В языках типа Си, где нет ООП, классов и интерфейсов/протоколов, примером реализации "интерфейса" делегата может быть структура с набором коллбеков.

Например:

// Objective-C
@protocol MyDelegate;
 
@interface Object: NSObject
@property (weak) id<MyDelegate> delegate;
@end

@protocol MyDelegate
-(void)myObject:(id)object didCompleteWithData:(id)data;
-(BOOL)shouldMyObjectDoTheWork(id)myObject;
@end

// Си
struct MyDelegate;
struct Object {
  MyDelegate *delegate;
};
struct MyDelegate {
  void (*didCompleteWithData)(Object *, void *data);
  BOOL (*shouldMyObjectDoTheWork)(Object *);
};

Таким образом, я прихожу к выводу, что "коллбеком" можно назвать нечто (какой-то callable: функция или функтор), что ожидается быть вызванным в некоторый момент времени. И это может быть одной из реализаций паттерна Delegate. Т.е. для меня коллбеки и делегаты это понятия разного уровня, одно может быть частным случаем другого.

Напоследок, коллбек это одна функция, а под Delegate я склонен подразумевать некий интерфейс, т.е. набор функций, объединённых общей идеей. Но, как я показал выше на примере на Си, можно симулировать такую группировку даже в языках без встроенного ООП.

Иногда разница хорошо раскрывается и самим названием.

Callback - обратный вызов (еще его называют замыканиями). Ожидается, что колбеки вызываются в конце асинхронной функции для возврата управления вызывающему коду. В любых других случаях их использование мне кажется моветоном.

Делегат - поведенческий паттерн, который применяется очень широко и за пределами программирования. И означает он передачу своей работы и ответственности другому лицу (в программировании – объекту).

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

Типичный пример – делегат нажатия на ячейку. По идее табличка сама должна отработать нажатие, но она не знает как. Поэтому часть работы по распознаванию нажатия она выполняет сама, а вот дальнейшую работу по открытию другого экрана, например, уже делегирует тому, кто знает что и как делать.

В противовес колбек. Типичный пример - анимации переходов – асинхронная функция, по выполнению которой мы бы хотели получить управление обратно и выполнить еще какие-то действия.

И перемешивать области применения инструментов - тоже огромнейший моветон. Это очень сильно снижает восприятие кода.

Спасибо за ваш комментарий.

  • Выбор в пользу скриншотов был сделан по причине того, что подсветка синтаксиса хорошо помогает понять семантику, когда ты новичок. Вставляя код блоками, подсветка отличается. Ссылка на GitHub с финальным проектом есть в конце статьи.

  • newtextForLabel и ViewControllerDelegate исправил, спасибо за внимательность.

  • Конечно, deinit() может не всегда отработать (дополнил этой сноской статью). Но в примере из статьи он отработает, меняя текст с задержкой добавляя наглядности.

Действительно забавно, что сам паттерн показан не совсем верно)

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

Может быть проще было сразу создать современный проект без всего этого?

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

Sign up to leave a comment.

Articles