Когда использовать responsesToSelector в objective-c
- (void)someMethod
{
if ( [delegate respondsToSelector:@selector(operationShouldProceed)] )
{
if ( [delegate operationShouldProceed] )
{
// do something appropriate
}
}
}
documentation говорит:
Меры предосторожности необходимы только для необязательных методов в формальном протоколе или методах неофициального протокола
Что это значит? Если я использую формальный протокол, я могу просто использовать [delegate myMethod]
?
Ответы
Ответ 1
Вы используете его в значительной степени, только когда думаете, что вам нужно: проверить, реализует ли объект метод, который вы собираетесь вызывать. Обычно это делается, когда у вас есть необязательные методы или неофициальный протокол.
Я когда-либо использовал respondsToSelector
, когда пишу код, который должен связываться с объектом-делегатом.
if ([self.delegate respondsToSelector:@selector(engineDidStartRunning:)]) {
[self.delegate engineDidStartRunning:self];
}
Иногда вы хотели бы использовать respondsToSelector
для любого возвращаемого метода и id
или generic NSObject
, где вы не уверены, что класс возвращаемого объекта.
Ответ 2
Просто чтобы добавить к тому, что сказал @kubi, в другой раз я использую его, когда метод был добавлен в уже существующий класс в более новой версии фреймворков, но мне все еще нужно быть обратно совместимым. Например:
if ([myObject respondsToSelector:@selector(doAwesomeNewThing)]) {
[myObject doAwesomeNewThing];
} else {
[self doOldWorkaroundHackWithObject:myObject];
}
Ответ 3
Как упоминается kubi respondsToSelector
, обычно используется, когда у вас есть экземпляр метода, который соответствует протоколу.
// Extend from the NSObject protocol so it is safe to call `respondsToSelector`
@protocol MyProtocol <NSObject>
// @required by default
- (void) requiredMethod;
@optional
- (void)optionalMethod;
@end
Учитывая и экземпляр этого протокола, мы можем безопасно вызвать любой требуемый метод.
id <MyProtocol> myObject = ...
[myObject requiredMethod];
Однако необязательные методы могут быть или не быть реализованы, поэтому вам нужно проверить их во время выполнения.
if ([myObject respondsToSelector:@selector(optionalMethod)])
{
[myObject optionalMethod];
}
Выполнение этого предотвратит сбой с непризнанным селектором.
Кроме того, вы должны объявлять протоколы как расширение NSObjects, т.е.
@protocol MyProtocol <NSObject>
Это потому, что протокол NSObject объявляет селектор respondsToSelector:
. В противном случае XCode подумает, что это небезопасно.
Ответ 4
Старый вопрос, но я научился быть очень осторожным с использованием таких вещей, как addTarget: @selector (fu:), потому что имя метода не проверено и не включено в рефакторинг XCODE. Это уже вызвало у меня неприятности. Итак, теперь я сделал привычкой всегда встраивать такие вещи, как addTarget или addObserver, в responsesToSelector-Check, например:
if([self respondsToSelector:@selector(buttonClicked:)]){
[self.button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
}else{
DebugLog(@"Warning - a class or delegate did not respond to selector in class %@", self);
}
Я знаю, что это не очень элегантно, но я бы скорее добавил код шаблона, чем неожиданное падение моих приложений в App Store.