Чтобы понять 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
в свой родительский контроллер представления. БУМ! У вас есть информация, переданная от ребенка до родителя. Отношения между этими двумя объектами даже не должны быть такими же тесными, как родитель / ребенок. Это контракт на обслуживание, так что пока объект, подписывающий соглашение, завершает сделку, внедряя необходимые методы, вы великолепны!
ПРИМЕЧАНИЕ. Делегаты должны быть слабыми / назначать свойства, иначе вы войдете в цикл сохранения, где ни один объект не может быть освобожден.
Надеюсь это поможет!