На даний момент я викладаю програмування на iOS, і одній концепції, якій мені дуже важко обернути голову, є делегування. Що це? Чому і як він використовується? Яка перевага? Технічне написання книги, яку я читаю, ускладнює розуміння.
На даний момент я викладаю програмування на iOS, і одній концепції, якій мені дуже важко обернути голову, є делегування. Що це? Чому і як він використовується? Яка перевага? Технічне написання книги, яку я читаю, ускладнює розуміння.
Відповіді:
Щоб зрозуміти delegates
, ти повинен розуміти protocols
.
A protocol
- це як договір на обслуговування. Коли об'єкт (найчастіше UIViewController
підклас, але не завжди) підписує цей контракт, він говорить "Мені цікаво надати логіку для підтримки повідомлення, яке ви мені надсилаєте". Це схоже на те, що NSNotificationCenter
стосується підписки на рівень інтересу, різниця полягає в об'єкті, який використовує делегування, і може мати лише один delegate
за одним, де кілька об'єктів можуть підписатись на один і той же NSNotification
.
Apple широко використовує делегацію. Однак все більше й більше ви бачите, що Apple пересуває багато своїх API blocks
, схожих з callbacks
іншими мовами.
Незважаючи на це, делегація допомагає підтримувати MVC, навіть якщо я можу стверджувати, що делегація - це сама по собі схема дизайну. Це допомагає відокремити моделі від контролерів. Як, наприклад, у прикладі Джона Картрайта, UITableView
вміє відображати рядки та розділи. Він знає, як повторно використовувати його UITableViewCells
з міркувань продуктивності. Він знає всі інші речі UIScrollView
знає. Але невідомо, які клітинки відображати. Він не знає, чим заповнити ці клітини. Він не знає, які клітини використовувати для даної задачі NSIndexPath
. Це дійсно має бути завданням контролера, у будь-якому разі. Делегування дозволяє перегляду таблиці завантажувати цю логіку без перегляду на об'єкт, який у будь-якому разі повинен відповідати за це.
Більше того, ви не зачинені в одному делеґаті протягом усього терміну експлуатації об'єкта. Ви можете дуже легко мати декілька джерел даних для даної задачі UITableView
та перемикати їх у потрібний час.
Отже, з одного боку, делегування чудово підходить для надання даних та реагування на взаємодії об'єкта. Ви побачите його у великій кількості класів UIKit, такий UITableView
, UIPickerView
, UICollectionView
і т.д.
Але делегування також дуже корисно, коли ви хочете передавати інформацію між об'єктами. Ви можете дуже легко створити власні протоколи та підписати власні об’єкти, щоб слідувати за ними. Крім того, протокольні методи @required
за замовчуванням, але ви можете вказати деякі методи@optional
. Це може дати вам приємну гнучкість, якщо вона вам потрібна. Скажімо, у вас є батьківський контролер подання та контролер дочірнього перегляду. Можливо, ви використовуєте новий Containment API для цього. Як правило, якщо вам потрібно передавати інформацію від батька дитині, ви робите це з властивістю. Зроблено. Але що робити, якщо вам потрібно передати інформацію від дитини назад до батька? Можливо, у дитини щось зміниться, і вам потрібно повідомити про це батька. Звичайно, ви могли б виконати якісь КВО за певними значеннями. Але, можливо, ви хочете знати, коли натискається кнопка. Просто створіть новий протокол у контролері дочірнього перегляду
@protocol MyChildDelegate
- (void)buttonWasTappedInChild:(MyChildViewController *)childViewController;
@end
@interface MyChildViewController : UIViewController
@property (weak, nonatomic) id <MyChildDelegate> delegate;
@end
У MyChildViewController після натискання кнопки просто перевірте, чи відповідає ваш делегат на повідомлення про делегат (якщо це потрібно, а ваш делегат не реалізує метод, ви зірвете. Ви можете зробити метод, @optional
якщо вам потрібно) та надішліть це:
- (IBAction)someButtonTapped:(id)sender {
if ([self.delegate respondsToSelector:@selector(buttonWasTappedInChild:)]) {
[self.delegate buttonWasTappedInChild:self];
}
}
Потім встановіть делегата вашого MyChildViewController у self
та виконайте його - (void)buttonWasTappedInChild:(MyChildViewController *)childViewController
в контролері батьківського перегляду. БУМ! У вас є інформація, передана від дитини до батька. Відносини між двома об'єктами навіть не повинні бути наближеними до батьків / дитини. Це договір на обслуговування, доки об'єкт, що підписує, тримає кінець угоди, застосовуючи необхідні методи, ви золото!
ПРИМІТКА: Делегати повинні бути слабкими / призначити властивості, інакше ви ввійдете в цикл збереження, де жоден об'єкт не може бути розміщений.
Сподіваюся, це допомагає!
Делегати - це об'єкти, які реалізують певні функції, коли не має сенсу реалізовувати ці функції на звичайному об'єкті. Це форма ін'єкції залежності.
Для конкретного прикладу подивіться на протокол UITableViewDelegate. Ці методи не мають сенсу безпосередньо переглядати таблицю, оскільки дії для вибору рядка перегляду таблиці будуть різними у кожному додатку, а може, і в кожному поданні таблиці. У делегата є метод, -tableView:didSelectRowAtIndexPath:
щоб ви могли створити об’єкт, який обробляє вибір рядків, не підкласируючи подання таблиці для кожного окремого дії, яке ви хочете здійснити.