2011-04-07 17 views
10

Nie rozumiem, dlaczego musimy wywoływać metodę setSelector na obiektach NSInvocation, gdy informacje te są już przekazywane za pośrednictwem invocationWithMethodSignature.Jaki jest cel metody setSelector w klasie NSInvocation?

Aby utworzyć NSInvocation obiektu możemy wykonać następujące czynności:

SEL someSelector; 
NSMethodSignature *signature; 
NSInvocation *invocation; 

someSelector = @selector(sayHelloWithString:); 

//Here we use the selector to create the signature 
signature = [SomeObject instanceMethodSignatureForSelector:someSelector]; 
invocation = [NSInvocation invocationWithMethodSignature:signature]; 

//Here, we again set the same selector 
[invocation setSelector:someSelector]; 
[invocation setTarget:someObjectInstance]; 
[invocation setArgument:@"Loving C" atIndex:2]; 

Zauważ, że minęliśmy wybieraka [SomeObject instanceMethodSignatureForSelector: someSelector]; i znowu [invocation setSelector:someSelector];.

Czy jest coś, czego mi brakuje?

+1

+1 - Dobrze jest zobaczyć tutaj pytanie, które nie było już zadawane (i odpowiadać) już milion razy, i nie jest napisane w żargonie błyskawicznym, który jest nieczytelny. :-) –

+0

Jeden mały punkt: 'signature = [SomeObject instanceMethodSignatureForSelector: someSelector];' powinno być 'signature = [[SomeObject class] instanceMethodSignatureForSelector: someSelector]; lub signature = [SomeObject methodSignatureForSelector: someSelector]; ' – Brynjar

Odpowiedz

8

Podpis nie jest selektorem. Selektor to nazwa wiadomości. Podpis określa parametry i wartość zwracaną. Możesz mieć wiele selektorów z tym samym podpisem i na odwrót. Jeśli spojrzysz na NSMethodSignature, zauważysz, że nie ma metody -selector; podpisy nie noszą określonego selektora.

Rozważmy następujący

- (void)setLocation:(CGFloat)aLocation; 
- (void)setLocation:(MyLocation*)aLocation; 

Mają ten sam wybierak @selector(setLocation:), ale różne podpisy.

- (void)setX:(CGFloat)x; 
- (void)setY:(CGFloat)y; 

Te mają ten sam podpis, ale różne selektory.

Selectors z języka programowania ObjC może być przydatnym źródłem informacji do zrozumienia tego.

+0

Chociaż dostaję to, co mówisz, wydaje się, że w twoim języku jest trochę nadmiarowości. Ustawiam selektor dwukrotnie (raz w podpisie i jeszcze raz w instancji wywołania). Osobiście uważam (IMHO), że wydajniejsze byłoby wyprowadzenie selektora (który w moim przypadku został zdefiniowany w 'someSelector') z podpisu. – haroldcampbell

+0

Nie można wyprowadzić selektora z podpisu. Możesz wyprowadzić sygnaturę z celu i selektora, pytając o cel (pamiętaj, że nowe metody i klasy mogą być tworzone w czasie wykonywania, nie możesz tego ustalić w czasie kompilacji).Masz rację, że może istnieć '+ invocationWithTarget: selector: arguments:' metoda skrótu (mój zespół ma kategorię, która dodaje coś podobnego). Nie byłoby bardziej wydajne, ponieważ zadzwoniłoby tylko do kodu, do którego dzwonisz, ale byłoby to trochę wygodniejsze. –

3

Podpis metody definiuje tylko typ zwrotu oraz liczbę i typ argumentów. Nie zawiera niczego o nazwie selektora. Na przykład, wszystkie te metody mają ten sam podpis, mimo o różnych selektorów:

-(void) foo:(NSString*)fooString; 
-(void) bar:(NSString*)barString; 
-(void) baz:(NSString*)bazString; 
0

Jest to rodzaj bocznej odpowiedzi, ale fakt, że można wykonać następujące czynności pomógł mi lepiej zrozumieć separację pomiędzy metodą sygnatury i selektory.

Ten kod jest w widoku kontrolera

NSMethodSignature *sig = nil; 
sig = [[self class] instanceMethodSignatureForSelector:@selector(viewDidAppear:)]; 
NSInvocation *myInvocation = nil; 
myInvocation = [NSInvocation invocationWithMethodSignature:sig]; 

[myInvocation setTarget:_somePopoverController]; 
[myInvocation setSelector:@selector(dismissPopoverAnimated:)]; 
BOOL animate = YES; 
[myInvocation setArgument:&animate atIndex:2]; 
[myInvocation invoke]; 

Od UIViewController za viewDidAppear: i UIPopoverController za dismissPopoverAnimated: zarówno podjęcia argument BOOL i powrotu nieważne, można utworzyć podpis metody przy użyciu jednego przełącznika, ale wysłać wezwanie do innego.