Чтобы понять delegates, ты должен понять protocols.
А protocolэто как контракт на обслуживание. Когда объект (чаще всего UIViewControllerподкласс, но не всегда) подписывает этот контракт, он говорит: «Я заинтересован в предоставлении логики для поддержки отправляемого мной сообщения». Это похоже на NSNotificationCenterотносительно подписавшись на уровне интересов, разница в том , объект , который использует делегирование может иметь только один delegateв то время, когда , как несколько объектов могут подписаться на то же самое NSNotification.
Apple использует делегирование повсеместно. Тем не менее, все больше и больше вы видите, что Apple переходит на многие из своих API blocks, которые похожи на callbacksдругие языки.
При этом делегирование помогает поддерживать MVC, хотя я бы сказал, что делегирование - это сама по себе модель проектирования. Это помогает отделить модели от контроллеров. Как в примере Джона Картрайта, a 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в свой родительский контроллер представления. БУМ! У вас есть информация, переданная от ребенка до родителя. Отношения между этими двумя объектами даже не должны быть такими же тесными, как родитель / ребенок. Это контракт на обслуживание, так что пока объект, подписывающий соглашение, завершает сделку, внедряя необходимые методы, вы великолепны!
ПРИМЕЧАНИЕ. Делегаты должны быть слабыми / назначать свойства, иначе вы войдете в цикл сохранения, где ни один объект не может быть освобожден.
Надеюсь это поможет!