Проверьте, существует ли метод

111

Есть ли способ проверить, существует ли метод в Objective-C?

Я пытаюсь добавить охранника, чтобы увидеть, есть ли у моего объекта метод, прежде чем его вызывать.

teepusink
источник
Также возникает вопрос, является ли это правильным в первую очередь, поскольку классы Objective-C могут реагировать на селекторы, которые они не объявили (через - forwardInvocation:).
Donal Fellows,

Ответы:

189
if ([obj respondsToSelector:@selector(methodName:withEtc:)]) {
   [obj methodName:123 withEtc:456];
}
kennytm
источник
72

Также существует селектор static message instanceRespondToSelector: (SEL) Вы бы назвали его так:

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

или вот так:

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

Это может быть полезно, если вы хотите вызвать один конструктор или другой в зависимости от этого (я имею в виду, прежде чем иметь сам экземпляр).

Рикар Перес дель Кампо
источник
1
Чем отличается instanceRespondToSelector от RespondsToSelector?
CReaTuS
1
Основное отличие состоит в том, что одно - это сообщение экземпляра (чтобы проверить, существует ли определенное сообщение экземпляра), а другое - сообщение класса (чтобы проверить, существует ли сообщение определенного класса).
Рикард Перес дель Кампо,
1
+1 для [MyClass instanceRespondToSelector]. Мне это было нужно внутри метода создания init: при создании подкласса, возможно, необходимо вызвать один метод super init вместо других (устаревших), поскольку self еще не был создан, и responsedsToSelector всегда будет возвращать NO.
LightMan
12

Используйте respondsToSelector:. Из документации :

RespondsToSelector:

Возвращает логическое значение, которое указывает, реализует ли получатель или наследует метод, который может отвечать на указанное сообщение.

- (BOOL)respondsToSelector:(SEL)aSelector

Параметры
aSelector - селектор, который идентифицирует сообщение.

Возвращаемое значение,
YES если получатель реализует или наследует метод, который может отвечать на aSelector , в противном случае NO.

Карл Норум
источник
10

Вы ищете RespondsToSelector: -

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

Как сказал Донал, приведенное выше говорит вам, что foo определенно может справиться с получением селектора bar. Однако, если foo является прокси-сервером, который перенаправляет bar на некоторый базовый объект, который получит сообщение bar, то responsedsToSelector: скажет вам НЕТ, даже если сообщение будет перенаправлено объекту, который отвечает на bar.

Фрэнк Шеарар
источник
1

Проверка селекторов с помощью responsedsToSelector обычно выполняется только для методов делегата. Вы не должны использовать forwardInvocation или прокси для методов делегата. Если вам нужно использовать RespondsToSelector в других ситуациях, вы можете убедиться, что нет более подходящего способа разработки вашей программы.

Эрик
источник