2009-07-16 13 views
64

Czy istnieje metoda klasy równoważna z -respondsToSelector:?Metoda równoważna z odpowiednikiem -respondsToSelector:

Coś jak +respondsToSelector:?

Powód, dla którego pytam, ponieważ zaimplementowałem -respondsToSelector: na poziomie klasy, dostaję ostrzeżenie kompilatora: "found" -respondsToSelector: 'zamiast "+ responsesToSelector:' w protokole (s)".

Kod wygląda następująco:

Class <SomeProtocol> someClass = [someInstance class]; 

if ([someClass respondsToSelector:@selector(someSelector:)]) { 
    someVar = [someClass someSelector:someData]; 
} 

Odpowiedz

80

Aktualizacja po obejrzeniu Twoja edycja:

Obiekt klasy reaguje na respondsToSelector: dobrze, jak zapewne wiesz. W aplikacji testowej, można zrobić zarówno z poniższych bez żadnych ostrzeżeń kompilatora:

NSLog(@"Responds to selector? %i", [MyObject respondsToSelector:@selector(respondsToSelector:)]); 
NSLog(@"Responds to selector? %i", [[MyObject class] respondsToSelector:@selector(respondsToSelector:)]); 

Jednak już ogłoszony protokół o zmiennej, więc zakłada, że ​​obiekt klasy jesteś wskazując realizuje te metody. Najprostszym rozwiązaniem byłoby obsłużenie someClass jako id w celu wywołania respondsToSelector:. Nieco czystsze rozwiązanie byłoby zadeklarować swój własny @protocol który deklaruje +respondsToSelector:(SEL)selector, a następnie zadeklarować someClass następująco:

Class<SomeProtocol, ClassRespondingToSelector> someClass = ... 

Wreszcie, należy zgłosić błąd z Apple na http://bugreporter.apple.com. Dołącz prostą aplikację testową, aby było jasne, co robisz. Przyjmują takie raporty o błędach, nawet jeśli zostały zgłoszone w przeszłości, ponieważ pomagają im ustalać priorytety poprawek.

Ostatnia uwaga: jest to prawdopodobnie dzieje, ponieważ w teorii, można wybrało do realizacji przedmiotu głównego całkowicie oddzielone od NSObject iw tym przypadku, to nie reagować na -respondsToSelector:. -[NSObject respondsToSelector:] jest faktycznie zadeklarowany w protokole NSObject, a nie definicji klasy. Protokół NSObject jest w rzeczywistości miejscem, gdzie żyje się większość tego, co znamy jako NSObject. Można by się spierać, że powinno tam być także +respondsToSelector:, ale na razie nie jest. A ponieważ dostarczyłeś listę protokołów, a ta metoda nie istnieje, daje ci ostrzeżenie, abyś wiedział, co robisz.

+0

Wierzę, że w tym przypadku rzeczywiście chciałby rzucić na Class, a nie id. –

+7

To jest albo usunięta funkcja, albo odpowiedź jest niejasna. 'Class' nie odpowiada na' responsesToSelector: '. – RileyE

+0

Wypróbuj. Nie ma go w nagłówku, ale wykonaj 'id classObject = [klasa SomeClass]; [classObject odpowiadaToSelector:] ' –

9

Dobrze metoda klasy jest tylko metoda obiektu klasy, więc powinieneś być w stanie po prostu zrobić to

[MyClass respondsToSelector:@selector(...)] 
+0

dostaję ostrzeżenie kompilatora: „odnaleziono '-respondsToSelector:' zamiast '+ respondsToSelector:' w protokole (s) ". Jak pozbyć się ostrzeżenia o tym kompilatorze? – firstresponder

+0

Mogę pozbyć się ostrzeżenia kompilatora, upuszczając kwalifikator typu protokołu "". Dlaczego? Czy ta składnia nie jest poprawna? – firstresponder

+3

firstresponder: Objective-C jest dynamicznym językiem. Jeśli wyślesz wiadomość do "Klasy" lub "identyfikatora" bez zakwalifikowania tego typu dalej (z protokołem), kompilator zakłada, że ​​wykonujesz jakąś odpowiedź na selektor lub typową dla siebie kontrolę . Jeśli jednak określisz protokół lub (dla instancji) konkretną klasę, stanie się on pomocny i wykona czek dla ciebie. Ponieważ protokół, w którym zadeklarowałeś zmienną, nie ma deklaracji '+ replysToSelector:', kompilator podnosi ostrzeżenie. –

1

To, o czym myślę, że pytasz: Czy możesz zapytać klasę, czy odpowiada na +someMethod, czy też nie? Innymi słowy, myśląc o interfejsach API Cocoa Touch, chcesz:

[ [ UIView class ] respondsToSelector: @selector(buttonWithType:) ] -> NO 
[ [ UIButton class ] respondsToSelector: @selector(buttonWithType:) ] -> YES 

Ale to, co napisałem powyżej, nie działa zgodnie z oczekiwaniami. respondsToSelector: dotyczy tylko metod instancji. (W ten sposób oba wywołania zwrócą NIE). W ramach interfejsów API Cocoa nie ma odpowiednika dla klasy respondsToSelector:. Można jednak zadzwonić pod numer class_getClassMethod. Jeśli wynik nie jest równy NULL, metoda klasy, o którą pytasz o numer , to obecnie i możesz ją wywołać.

+8

To jest fałsz. 'responssToSelector:' działa dobrze na obiektach 'Class', aby zgłosić istnienie metod klasy. –

+0

Wstawiam głos temu kolesiowi, ponieważ był on poprawny w swoim podejściu 'class_getClassMethod'. Gdybym miał dość cierpliwości, aby przeczytać cały wątek, nie musiałbym wymyślać tego samego rozwiązania. – bioffe

+1

I down-vote to, ponieważ metody klasy * są * metody instancji na obiekcie klasy. – user102008

0

W Objective C, klasy są również obiektami, dzięki czemu można wysyłać wiadomości obiektowe. W szczególności możesz poprosić o klasę o numer -respondsToSelector:. Nie można jednak wysyłać metod klasy na obiekty nie-klasy.

5

Możesz używać następującego instancesRespondToSelector: od iOS 2.0, więc gdzie z instancją klasy możesz zrobić;

[myInstance respondsToSelector: @selector(...)]; 

z klasą można użyć

[myClass instanceRespondsToSelector: @selector(...)]; 
// or 
[[myInstance class] instanceRespondsToSelector: @selector(...)]; 

Jakie będą zachowywać się jak +(BOOL) respondsToSelector

+6

To odpowiada, jeśli instancje klasy odpowiedziałyby na selektor, a nie gdyby klasa sama reagowała statycznie na selektor. – Jonny

Powiązane problemy