Sprawdź, czy metoda istnieje

111

Czy istnieje sposób na sprawdzenie, czy metoda istnieje w Objective-C?

Próbuję dodać strażnika, aby sprawdzić, czy mój obiekt ma metodę przed jej wywołaniem.

teepusink
źródło
Pojawia się również pytanie, czy jest to właściwe podejście w pierwszej kolejności, skoro klasy Objective-C mogą odpowiadać na selektory, których nie zadeklarowały (przez - forwardInvocation:).
Donal Fellows

Odpowiedzi:

189
if ([obj respondsToSelector:@selector(methodName:withEtc:)]) {
   [obj methodName:123 withEtc:456];
}
kennytm
źródło
72

Istnieją również statyczne instancje wiadomościRespondToSelector : (SEL) selector Można to nazwać tak:

[MyClass instancesRespondToSelector:@selector(someMethod:withParams:)]

lub tak:

[[myObject class] instancesRespondToSelector:@selector(someMethod:withParams:)]

Może to być przydatne, jeśli chciałbyś wywołać jednego konstruktora lub innego w zależności od tego (mam na myśli, zanim będziesz mieć samą instancję).

Ricard Pérez del Campo
źródło
1
Czym różni się instancesRespondToSelector od respondsToSelector?
CReaTuS,
1
Główną różnicą jest to, że jeden jest komunikatem instancji (aby sprawdzić, czy komunikat określonej instancji istnieje), a drugi jest komunikatem klasy (aby sprawdzić, czy komunikat określonej klasy istnieje).
Ricard Pérez del Campo
1
+1 dla [instancji MyClassRespondToSelector]. Potrzebowałem tego w metodzie tworzenia init: kiedy podklasy mogą być konieczne, aby wywołać jedną metodę super init zamiast innych (przestarzałe), ponieważ self nie zostało jeszcze utworzone i respondsToSelector zawsze zwróci NIE.
LightMan,
12

Użyj respondsToSelector:. Z dokumentacji :

respondsToSelector:

Zwraca wartość logiczną wskazującą, czy odbiorca implementuje, czy dziedziczy metodę, która może odpowiedzieć na określony komunikat.

- (BOOL)respondsToSelector:(SEL)aSelector

Parametry
aSelector - selektor identyfikujący wiadomość.

Wartość zwracana ,
YESjeśli odbiorca implementuje lub dziedziczy metodę, która w przeciwnym razie może odpowiedzieć na element aSelectorNO .

Carl Norum
źródło
10

Szukasz odpowiedziToSelector: -

if ([foo respondsToSelector: @selector(bar)] {
  [foo bar];
}

Jak mówi Donal, powyższe mówi ci, że foo zdecydowanie poradzi sobie z otrzymaniem selektora paska. Jednakże, jeśli foo jest proxy, które przekazuje bar do jakiegoś bazowego obiektu, który otrzyma komunikat bar, to respondsToSelector: powie Ci NIE, nawet jeśli wiadomość zostanie przekazana do obiektu, który odpowiada na bar.

Frank Shearar
źródło
1

Sprawdzanie selektorów za pomocą respondsToSelector jest zwykle tylko dla metod delegata. Nie należy używać forwardInvocation ani serwerów proxy dla metod delegatów. Jeśli potrzebujesz użyć respondsToSelector w innych sytuacjach, możesz upewnić się, że nie ma bardziej odpowiedniego sposobu projektowania programu.

Eric
źródło