2012-01-28 12 views
10

Naprawdę dopiero zaczynam rozwijać IOS, ale mam kilka lat rozwoju ASP.net przez C#. Szczerze mówiąc, nigdy wcześniej nie miałem prawdziwej potrzeby zrozumienia delegatów/wydarzeń itp. Wiem, że używam ich podczas programowania web.forms, ale wiele funkcji jest zajętych przez ramy, za kulisami .Delegaci w IOS - Wymagane pewne wyjaśnienie

Teraz, kiedy pracuję w IOS, jestem zmuszony spróbować zrozumieć, jak funkcjonują (przypuszczam tutaj, że teoria delegatów/wydarzeń jest taka sama w różnych językach, może się mylę). Zresztą następujący wiersz kodu w IOS:

if ([self.delegate respondsToSelector:@selector(startImporting:)]) 
{ 
      [self.delegate startImporting:self]; 
} 

mam rację sądząc, że w pseudo kod, to znaczy coś wzdłuż linii:

Jeśli metoda/klasy wywołanie tej metody ma metoda w nim zwana "startImporting", a następnie wywołaj metodę "startImporting" w klasie wywołującej.

Mam nadzieję, że jest jasne. Jeśli to przypadek to byłoby to w zasadzie taka sama jak o statycznej metody w C#, który można nazwać coś podobnego:

myImportClass.startImporting(); 

Przypuszczalnie nie, czy to w jaki sposób to zrobić. Czy więc brakuje mi całego punktu delegatów, ich korzyści itp.? Czytałem, co robią w kółko i kiedy ma to sens, nigdy się nie klika, nigdy (i tak w przypadku formularzy internetowych) nie widziałem korzyści z ich używania.

Staje się to coraz ważniejsze, ponieważ używam wyrażeń lambda w .net i są one ściśle związane z delegacjami w C#, więc gdy tylko mogę zacząć ich używać, wolałbym wiedzieć, dlaczego i jakie korzyści przynosi delegatom. faktycznie są.

+0

Tutaj http://stackoverflow.com/questions/30662032/ios-callback-function -from-library zawiera szczegółowe informacje na temat implementacji dla delegatów. –

Odpowiedz

45

Wzór delegacja w kakao służy do informowania (sprawozdanie z postępu prac, etc .) lub zapytanie (zapytaj o poświadczenia itp.) inny obiekt, nie wiedząc o tym zbyt wiele.

Zwykle używa się protokołu do definiowania metod, które należy wywołać u delegata, a następnie delegata musi dostosować się do tego protokołu. Możesz także dodać metody, których delegat nie musi implementować (opcjonalnie). Kiedy to zrobisz, będziesz musiał zadzwonić -respondsToSelector :, ponieważ nie wiesz, czy delegat chce wywołać konkretną metodę, czy nie.

przykład:
Masz klasę, która produkuje coś, nazwijmy to Machine i pracownik klasy Worker.Maszyna musi być dostosowane do tego zadania:

Machine *machine = [[Machine alloc] init]; 
[machine prepareWithParameters:myParameters]; 

Teraz, gdy mamy maszynę chcemy produkować ogromne ilości Stuff:

[machine produceStuff]; 

porządku, skończymy. Ale skąd wiemy, kiedy wyprodukowano jednostkę o numerze Stuff? Mogliśmy nasz pracownik stale stoi obok naszej maszynie i czekać:

while (![machine isFinished]) { 
    if ([machine didProduceStuff]) { 
     Stuff *stuff = [machine producedStuff]; 
     [self doSomethingWithStuff:stuff]; 
    } 
    else { 
     // Get a very large coffee... 
    } 
} 

Czy nie byłoby wspaniale, gdyby maszyna nie informują nas automatycznie, gdy jest to zrobione z wytwarzania jednostki Stuff?

@protocol MachineDelegate <NSObject> 
@optional 
    - (void) machine:(Machine *)machine didProduceStuff:(Stuff *)stuff; 
@end 

Dodajmy worker jako delegat machine:

Worker *worker; 
Machine *machine = [[Machine alloc] init]; 
[machine prepareWithParameters:myParameters]; 
[machine setDelegate:worker]; // worker does conform to <MachineDelegate> 

[machine produceStuff]; 

Kiedy Machine odbywa produkcji czegoś, to wtedy rozmowy:

if ([[self delegate] respondsToSelector:@selector(machine:didProduceStuff:)]) 
    [[self delegate] machine:self didProduceStuff:stuff]; 

worker wtedy otrzyma tę metodę i może coś zrobić:

- (void) machine:(Machine *)machine didProduceStuff:(Stuff *)stuff { 
    [self doSomethingWithStuff:stuff]; 
    if ([machine isFinished]) 
     [self shutDownMachine:machine]; 

}

Czy pracownik nie jest o wiele bardziej wydajny i łatwiejszy? Teraz może zrobić coś bardziej produktywnego niż stanie obok maszyny, gdy maszyna wciąż produkuje. Można teraz dodać jeszcze więcej sposobów, aby MachineDelegate:

@protocol MachineDelegate <NSObject> 
@required 
    - (void) machineNeedsMaintenance:(Machine *)machine; 
    - (void) machine:(Machine *)machine fatalErrorOccured:(Error *)error; 
    - (BOOL) machine:(Machine *)machine shouldContinueAfterProductionError:(Error *)error; 
@optional 
    - (void) machineDidEnterEcoMode:(Machine *)machine; 
    - (void) machine:(Machine *)machine didProduceStuff:(Stuff *)stuff; 
@end 

Delegaci mogą być również wykorzystywane do zmiany zachowania obiektu bez instacji go:

@protocol MachineDelegate <NSObject> 
@required 
    - (Color *) colorForStuffBeingProducedInMachine:(Machine *)machine; 
    - (BOOL) machineShouldGiftWrapStuffWhenDone:(Machine *)machine; 
@end 

Mam nadzieję, że mogę pomóc w zrozumieniu korzyści abstrahować twój kod, używając trochę delegatów.

+2

Niezwykle wszechstronna odpowiedź. Dziękuję Ci! –

+2

Doskonale! zaczęli rozumieć delegatów po przeczytaniu tej odpowiedzi :) –

+0

Jest to najlepszy przykład delegatów, o którym dotąd się zetknąłem –

1

Zrozumienie modelu MVC i korzystania z protokołów i powiadomień ma kluczowe znaczenie dla zrozumienia wykorzystania i celu delegatów. Pomyśl o nich jako o typach osób reagujących na różne zdarzenia związane z konkretnym działaniem.

Hera kilka przydatnych linków w StackOverflow:

Nadzieja pomaga

0

delegaci są przydatne w uzyskaniu zwrotnych od drugiej klasy

dlaczego więc używać Delegat: to nazywamy metodę w klasie ... to normalne ... jeśli chcemy instancja klasy, aby nas oddzwoń ... w tym miejscu przydają się delegaci ...

prosty przykład: u pobieranie utworów z witryny przy użyciu metody na jednej klasie po ukończeniu pobierania klasy i wybraniu klasy, aby udzieliła informacji ..

//protocol declaration 
    @protocol DownloadProtocol <NSObject> 
    -(void)OnFinish; 
    @end 

//SOng download class 
@interface songs 
@property(Strong,nonatomic) id<DownloadProtcol> delegate; 
-(void)Download; 
@end 
@implementation songs 
-(void)Download 
{ 

///the code to download goes here 

[self callTheCallingClass]; 

} 

-(void)CallTheCallingClass 
{ 
[self.delegate OnFinish]; 
} 
@end 

// 
@interface mainclass<DownloadProtocol> 

@end 

@implementation mainclass 

-(void)viewDidload 
{ 
Songs *s=[[SOngs alloc]init]; 
s.delegate=self; 
[s download]; 
} 
-(void)OnFinish 
{ 
    NSlog(@"Called"); 
} 
@end 

1) patrz Przekazanie odbywa się poprzez protokół w Objective C Myślę, że u można zrozumieć składnię tego ...

2) W klasie pieśni tworzymy obiekt dla tego protokołu możemy zachować to typ jako ID ... bcuz typ nie jest znany podczas kompilacji.

3) w klasie piosenek po zakończeniu pobierania nazywamy metodę protokołu ...

4) W głównym klasy najpierw przyjąć protokół składni klasa powyższe jest składnia tej

5) mamy instancję klasy piosenek

6), a następnie przypisać głównego obiektu klasy (self) delegować klasy piosenkami

7) to musimy zastosować klasę protokołu w .m dodając nazwę metody z protokołem

8), więc od teraz, gdy klasa piosenki wywołać metodę protokołu poprzez zmiennej instancji delegat .... metoda z protocl przyjęcie na głównej klasy pobiera uruchomić

wypróbować ten kod nadzieję, że to pomaga ...

jeśli u chcesz więcej informacji na ten temat google go jako delegata wzorca projektowego

głównym benifit jest promuje luźno programowanie ...