Design Mønstre: Delegering
25
Del
3
Del
Dette Cyber mandag Envato Tuts + kurs vil bli redusert å bare $ 3. Ikke gå glipp av.
Delegasjonen mønsteret er blant de vanligste mønstrene i iOS og OS X utvikling. Det er et enkelt mønster som er mye brukt av Apples rammer og selv de enkleste iOS applikasjonen utnytter delegasjon å gjøre sitt arbeid. La oss begynne med å se på definisjonen av delegasjonen.
1. Hva er Delegering?
Definisjon av
Definisjonen av delegasjonen mønsteret er kort og enkel. Dette er hvordan Apple definerer mønsteret., En delegat er et objekt som opptrer på vegne av, eller i samarbeid med, annet objekt når objektet møter en hendelse i et program.
La oss bryte det ned. Delegasjonen mønster involverer to objekter, representanten og delegere objekt. Den UITableView klasse, for eksempel definerer en delegat eiendom som den delegater hendelser. Representanten egenskapen må samsvare med UITableViewDelegate protokollen, som er definert i header fil av UITableView klassen.
I dette eksemplet er tabellvisningen eksempel delegere objekt. Representanten er vanligvis en visning kontrolleren, men det kan være et objekt som er i samsvar med den UITableViewDelegate protokollen. Hvis du ikke er kjent med protokoller, sams en klasse til en protokoll om det implementerer de nødvendige metoder for protokollen. . Vi skal se på et eksempel litt senere
Når brukeren kraner rad i tabellvisningen, varsler tabellvisningen sin delegat ved å sende den en melding til Tableview (_: didSelectRowAtIndexPath :). Det første argumentet med denne metoden er tabellvisningen sender meldingen. Det andre argumentet er indeksen banen av raden brukeren avlyttet.
Tabellvisningen bare varsler sin delegat av denne hendelsen. Det er opp til representanten for å bestemme hva som skal skje når en slik hendelse inntraff. Dette separasjon av ansvar, som du vil lære i et øyeblikk, er en av de viktigste fordelene med delegasjonen mønster.
Fordeler
Gjenbruk
Delegasjon har flere fordeler, den første er gjenbruk. Fordi tabellen vise delegater brukermedvirkning til sin delegat, ikke tabellvisningen ikke trenger å vite hva som må skje når en av sine rekker er avlyttet.
Sagt på en annen, kan visningen tabellen forblir uvitende om gjennomføringen detaljer om hvordan brukermedvirkning håndteres av programmet. Dette ansvaret er delegert til delegat, utsikt controller for eksempel.
Den direkte fordel er at UITableView klassen kan brukes som den er i de fleste situasjoner. Mesteparten av tiden, er det ingen grunn til å underklasse UITableView å tilpasse den til programmets behov.
Løse Coupling
En annen viktig fordel med delegasjonen er løs kobling. I min artikkel om enkeltfødte, jeg understreke at tett kopling bør unngås så mye som mulig. Delegering er et design mønster som aktivt fremmer løs kopling. Hva mener jeg med det?
UITableView klassen er koplet til sin delegat å gjøre sitt arbeid. Hvis ingen delegat er knyttet til bordvisningen kan visningen tabellen ikke håndtere eller svare på brukermedvirkning. Dette betyr at det må være en viss grad av kobling. Tabellen utsikt og delegat, derimot, er løst koplet, fordi hver klasse som implementerer UITableViewDelegate protokollen kan fungere som tabellvisningen delegat. Resultatet er et fleksibelt og løst koplet objekt grafen.
Separasjon Ansvarsområde
En mindre kjent fordel av delegasjonen er separasjon av ansvar. Når du oppretter et objekt graf, er det viktig å vite hvilke objekter som er ansvarlig for hvilke oppgaver. Delegasjonen mønsteret gjør dette veldig klart.
I tilfelle av UITableView klassen, er representanten fra tabellvisningen ansvarlig for håndtering av brukermedvirkning. Tabellvisningen selv er ansvarlig for å oppdage brukermedvirkning. Dette er et klart skille mellom ansvar. Et slikt skille gjør jobben din som en utvikler mye enklere og klarere.
2. Eksempel
Det er noen varianter av delegasjonen mønster. La oss fortsette med videre utforsking av UITableViewDelegate protokollen.
Delegasjon
UITableViewDelegate protokollen må implementeres ved bordet visningens delegat. Tabellvisningen varsler sin delegat gjennom UITableViewDelegate protokollen om brukermedvirkning, men den bruker også representanten for oppsettet.
En viktig forskjell mellom Swift og Objective-C er muligheten til å markere protokoll metoder som valgfritt. I Objective-C, er metodene for en protokoll som kreves som standard. Fremgangsmåtene ifølge fore UITableViewDelegate protokollen, men er valgfrie. Med andre ord, er det mulig for en klasse for å samsvare med UITableViewDelegate protokoll uten å gjennomføre noen av protokollens metoder.
i Swift imidlertid en klasse i samsvar med en bestemt protokoll er nødvendig for å implementere enhver metode definert av protokollen. Dette er mye tryggere siden delegere objektet ikke trenger å verifisere om representanten implementerer en protokoll metode. Dette subtil, men viktig, forskjell er illustrert senere i denne opplæringen når vi implementere delegasjonen mønster.
Data Source
Det er et annet mønster som er nært knyttet til delegasjonen mønster, datakilden mønster. Den UITableViewDataSource protokollen er et eksempel på dette mønsteret. Den UITableView klasse eksponerer en datakilde eiendom som er av type UITableViewDataSource (id < UITableViewDataSource > i Objective-C). Dette betyr at tabellvisningen datakilde kan være et objekt som implementerer UITableViewDataSource protokollen.
datakildeobjektet er ansvarlig for å håndtere datakilden til objektet det er datakilde. Det er viktig å merke seg at datakildeobjektet er ansvarlig for å holde en referanse til de poster det utsetter til målet objekt, for eksempel en tabellvisning eller samling utsikt.
En tabellvisning, for eksempel, spør sin data kilden for data det er behov for å vise. Tabellvisningen er ikke ansvarlig for å holde tak i de data objekter den trenger for å vise. Denne rollen er overlevert til datakildeobjektet.
Datakilden mønsteret passer fint i Model-View-Controller eller MVC mønsteret. Hvorfor det? En tabellvisning, for eksempel, er en del av utsikten lag. Det trenger ikke og bør ikke vite om modellen lag og er ikke ansvarlig for håndtering av data som kommer fra modellen laget. Dette innebærer at datakilden for en tabellvisning, eller noen annen visning komponent som implementerer datakilden mønster, er ofte en kontroller av noe slag. På iOS, er det vanligvis en UIViewController underklasse.
Metoden underskrifter fra en datakilde protokoll følger samme mønster som de av en delegat protokollen. Objektet sende meldinger til datakilden føres som første argument. Datakilden protokollen bør bare definere metoder som er knyttet til data som blir brukt av den anmodende objektet.
En tabellvisning, for eksempel, spør sin datakilde for antall seksjoner og rader det skal vise. Men den varsler også datakilden som en rad eller seksjon ble satt inn eller slettet. Det siste er viktig fordi datakilden trenger å oppdatere seg selv å reflektere de synlige i visningen tabellen endringer. Hvis tabellen og datakilde komme ut av sync, dårlige ting skje.
3. Implementering
Objective-C
Implementering representanten mønsteret er ganske enkelt nå som vi forstår hvordan det fungerer. Ta en titt på følgende Objective-C eksempel
#import < UIKit /UIKit.h >protocol AddItemViewControllerDelegate;interface AddItemViewController. UIViewController @ eiendom (svak, nonatomic) id < AddItemViewControllerDelegate > delegat; @ enden @ protokollen AddItemViewControllerDelegate < NSObject > - (void) viewControllerDidCancel: (AddItemViewController *) viewController, - (void) viewController: (AddItemViewController *) viewController didAddItem: (NSString *) element; @ Optional (BOOL) viewController: (AddItemViewController *) viewController validateItem: (NSString *) element;end
Vi erklærer en klasse, AddItemViewController, som strekker UIViewController. Klassen erklærer en eiendom, delegat, av type id < AddItemViewControllerDelegate >. Oppmerksom på at eiendommen er merket som svak, noe som betyr at en AddItemViewController eksempel holder en svak referanse til sin delegat.
Vær også oppmerksom på at jeg har lagt et framtids protokoll erklæring under import uttalelse av UIKit rammeverket. Dette er nødvendig for å unngå en kompilator advarsel. Vi kunne flytte protokollen erklæring under import uttalelse, men jeg foretrekker å sette den under klassen grensesnitt. Dette er noe mer enn en personlig preferanse.
Protokollen erklæringen er også ganske enkel. Den AddItemViewControllerDelegate protokollen forlenger NSObject protokollen. Dette er ikke obligatorisk, men det vil vise seg å være svært nyttig. Vi vil finne ut hvorfor det er litt senere.
AddItemViewControllerDelegate protokollen erklærer to nødvendige metoder og én valgfri metode. Som jeg nevnte tidligere, er det en god praksis å passere delegere objekt som første parameter for hver delegat metode for å informere representanten som objekt sender meldingen.
De nødvendige metoder varsle representanten om en hendelse, en kanselering eller et tillegg. Den valgfrie metoden spør representanten for tilbakemeldinger. Det forventer representanten for å gå tilbake JA eller NEI.
Dette er første del av delegasjonen puslespill. Vi har erklært en klasse som erklærer en delegat eiendom, og vi har erklært en delegat protokollen. Den andre brikken i puslespillet er å påberope representanten metoder i AddItemViewController klassen. La oss se hvordan det fungerer
I gjennomføringen av AddItemViewController klassen, vi implementere en avbryte. Handling. Denne handlingen kan være koblet til en knapp i brukergrensesnittet. Hvis brukeren kraner på knappen, er representanten varslet om denne hendelsen, og som et resultat, kunne representanten avviser AddItemViewController eksempel Anmeldelser - (IBAction) avbryte:. (Id) avsender {if (self.delegate & & [self.delegate respondsToSelector:selector (viewControllerDidCancel :)]) {[self.delegate viewControllerDidCancel bolig:]; }}
Det anbefales å kontrollere at representanten objektet ikke er lik null, og at den implementerer representanten metoden vi er i ferd med å påkalle, viewControllerDidCancel :. Dette er enkel takket være respondsToSelector: metode, erklærte i NSObject protokollen. Dette er grunnen til at AddItemViewControllerDelegate protokollen strekker NSObject protokollen. Ved å utvide NSObject protokollen, får vi denne funksjonaliteten gratis
Du kan utelate sjekk for representanten eiendommen blir null, siden respondsToSelector. Returnerer null dersom representanten eiendommen er null. Jeg pleier å legge denne kontrollen siden det viser tydelig hva vi tester.
Den tredje og siste brikken i puslespillet er gjennomføringen av representanten protokollen ved representanten objektet. Følgende kodebiten viser etableringen av en AddItemViewController forekomst og gjennomføringen av en av de delegere metoder Anmeldelser - (IBAction) AddItem:. (Id) avsender {//Initial View Controller AddItemViewController * viewController = [[AddItemViewController Alloc] init ]; //Konfigurer View Controller [viewController setDelegate bolig:]; //Present View Controller [selv presentViewController: viewController animerte: JA ferdigstillelse: null];} - (void) viewControllerDidCancel: (AddItemViewController *) viewController {//Avvis Legg til element View Controller ...}
Ikke glem å sams klassen som fungerer som delegat til AddItemViewControllerDelegate protokollen som vist nedenfor. Du kan legge til denne i klassen grensesnitt eller i en privat klasse forlengelse
#import "AddItemViewController.h"@interface ViewController (). ≪ AddItemViewControllerDelegate >end
Swift
I Swift, den delegasjon mønsteret er like lett å gjennomføre, og du vil finne at Swift gjør delegasjonen litt mer elegant. La oss gjennomføre eksempelet ovenfor i Swift. Dette er hva AddItemViewController klassen ser ut i Swift
import UIKitprotocol AddItemViewControllerDelegate: NSObjectProtocol {func viewControllerDidCancel (viewController: AddItemViewController) func viewController (viewController: AddItemViewController, didAddItem: String) func viewController (viewController: AddItemViewController, validateItem: String). - > Bool} class AddItemViewController: UIViewController {var delegat: AddItemViewControllerDelegate? func avbryte (avsender: AnyObject) {delegere .viewControllerDidCancel (egen-)?}}
Protokollen erklæring ser litt annerledes i Swift. Legg merke til at AddItemViewControllerDelegate protokollen utvider NSObjectProtocol stedet for NSObject protokollen. I Swift, kan klasser og protokoller ikke ha samme navn, som er grunnen til NSObject protokollen er et annet navn i Swift.
delegat Eiendommen er en variabel av type AddItemViewControllerDelegate ?. Legg merke til spørsmålstegnet på slutten av protokollen navn. Representanten Eiendommen er en valgfri.
I avbryte (_ :) metode, påberope vi viewControllerDidCancel (_ :) delegat metode. Det eneste linje viser hvor elegant Swift kan være. Vi trygt pakke representanten eiendom før påberope representanten metoden. Det er ikke nødvendig å sjekke om representanten implementerer viewControllerDidCancel (_ :) metoden siden hver metode for en protokoll er nødvendig i Swift.
La oss nå se på ViewController klassen, som implementerer AddItemViewControllerDelegate protokollen. Grensesnittet viser oss at ViewController klassen utvider UIViewController klasse og vedtar AddItemViewControllerDelegate protokollen
import UIKitclass ViewController. UIViewController, AddItemViewControllerDelegate {func AddItem (send: AnyObject) {//Initial View Controller la viewController = AddItemViewController () //konfigurere View Controller viewController.delegate = selv //Present View Controller presentViewController (viewController, animert: true, ferdigstillelse: null)} func viewControllerDidCancel (viewController: AddItemViewController) {//Avvis Legg til element View Controller ...} func viewController (viewController: AddItemViewController, didAddItem: String) {} func viewController (viewController: AddItemViewController, validateItem: String) - > Bool {}}
I AddItem (_ :) metode, vi initial en forekomst av AddItemViewController klassen, satt sin delegat eiendom, og presentere det for brukeren. Merk at vi har implementert hver delegat metoden i AddItemViewControllerDelegate protokollen. Hvis vi ikke gjør det, vil kompilatoren fortelle oss at ViewController klassen ikke er i overensstemmelse med den AddItemViewControllerDelegate protokollen. Prøv ut dette ved å kommentere ut en av de delegere metoder.
Konklusjon
Delegasjon er et mønster du vil komme over ofte når du utvikler iOS og OS X-programmer. Cocoa er avhengig tungt på dette design mønster, så det er viktig å bli kjent med den.
Siden introduksjonen av blokker, for noen år siden, har Apple sakte tilbudt en alternativ blokker basert API til noen delegasjon implementeringer. Noen utviklere har fulgt ledelsen Apples ved å tilby sine egne blokker-baserte alternativer. Den populære AFNetworking bibliotek, for eksempel, er veldig avhengig blokker i stedet for delegasjonen, som resulterer i en elegant, intuitiv API.