Aby zrozumieć delegates
, musisz zrozumieć protocols
.
A protocol
jest jak umowa serwisowa. Kiedy obiekt (najczęściej UIViewController
podklasa, ale nie zawsze) podpisuje tę umowę, mówi: „Jestem zainteresowany logiką, aby poprzeć przesłaną mi wiadomość”. Jest to podobne do NSNotificationCenter
zapisywania się na pewien poziom zainteresowania, z tą różnicą, że obiekt, który korzysta z delegacji, może mieć tylko jeden delegate
na raz, ponieważ wiele obiektów może zarejestrować się na taki sam poziom NSNotification
.
Apple szeroko rozpowszechnia delegowanie uprawnień. Coraz częściej jednak Apple przenosi wiele swoich interfejsów API blocks
, które są podobne do callbacks
innych języków.
Biorąc to pod uwagę, delegacja pomaga utrzymać MVC, nawet jeśli twierdzę, że delegacja jest sama w sobie wzorcem projektowym. Pomaga oddzielić modele od sterowników. Tak jak w przykładzie Johna Cartwrighta, UITableView
umie on wyświetlać wiersze i sekcje. Wie, jak wykorzystać ponownie UITableViewCells
ze względu na wydajność. Zna wszystkie inne rzeczy, które UIScrollView
zna. Ale nie wie, które komórki wyświetlić. Nie wie, co wypełnić tymi komórkami. Nie wie, które komórki użyć ponownie dla danego NSIndexPath
. W każdym razie to naprawdę powinno być zadaniem kontrolera. Delegowanie umożliwia widokowi tabeli odciążenie tej logiki braku widoku na obiekt, który i tak powinien ponosić tę odpowiedzialność.
Co więcej, nie jesteś zamknięty w jednym uczestniku przez cały okres życia obiektu. Możesz bardzo łatwo mieć wiele źródeł danych dla danego UITableView
i przełączać je w czasie wykonywania w razie potrzeby.
Z jednej strony delegowanie świetnie nadaje się do dostarczania danych i reagowania na interakcje z obiektem. Zobaczysz go w wielu klasach UIKit taka UITableView
, UIPickerView
, UICollectionView
, etc.
Ale delegowanie jest również bardzo przydatne, gdy chcesz przekazywać informacje między obiektami. Możesz bardzo łatwo tworzyć własne protokoły i rejestrować własne obiekty, aby ich przestrzegać. Ponadto metody protokołów są @required
domyślnie, ale można określić niektóre z nich@optional
. To może dać ci niezłą elastyczność, jeśli jej potrzebujesz. Załóżmy, że masz nadrzędny kontroler widoku i kontroler widoku potomnego. Być może używasz do tego nowego interfejsu API Containment. Zazwyczaj, jeśli musisz przekazać informacje od rodzica do dziecka, robisz to z właściwością. Gotowe. Ale co, jeśli musisz przekazać rodzicowi informacje od dziecka? Może coś się zmienia u dziecka i musisz powiadomić rodzica. Pewnie, możesz zrobić KVO na niektórych wartościach. Ale może chcesz wiedzieć, kiedy zostanie naciśnięty przycisk. Wystarczy utworzyć nowy protokół w kontrolerze widoku potomnego
@protocol MyChildDelegate
- (void)buttonWasTappedInChild:(MyChildViewController *)childViewController;
@end
@interface MyChildViewController : UIViewController
@property (weak, nonatomic) id <MyChildDelegate> delegate;
@end
Po stuknięciu przycisku w MyChildViewController, po prostu sprawdź, czy Twój delegat odpowiada na wiadomość delegowaną (jeśli jest to wymagane, a Twój delegat nie implementuje metody, @optional
nastąpi awaria. Możesz wykonać metodę, jeśli trzeba) i wysłać to:
- (IBAction)someButtonTapped:(id)sender {
if ([self.delegate respondsToSelector:@selector(buttonWasTappedInChild:)]) {
[self.delegate buttonWasTappedInChild:self];
}
}
Następnie ustaw delegata swojego MyChildViewController na self
i zaimplementuj go - (void)buttonWasTappedInChild:(MyChildViewController *)childViewController
w nadrzędnym kontrolerze widoku. BUM! Przekazałeś informacje od dziecka do rodzica. Relacja między tymi dwoma obiektami nie musi nawet być tak bliska jak rodzic / dziecko. Jest to umowa serwisowa, więc dopóki rejestracja obiektu utrzyma koniec okazji poprzez wdrożenie wymaganych metod, jesteś złoty!
UWAGA: Delegaci powinni być słabi / przypisywać właściwości, w przeciwnym razie przejdziesz do cyklu przechowywania, w którym nie można cofnąć przydziału żadnego obiektu.
Mam nadzieję że to pomoże!