Когда использовать responsedsToSelector в target-c
- (void)someMethod
{
if ( [delegate respondsToSelector:@selector(operationShouldProceed)] )
{
if ( [delegate operationShouldProceed] )
{
// do something appropriate
}
}
}
В документации сказано:
Меры предосторожности необходимы только для необязательных методов в формальном протоколе или методов неформального протокола
Что это значит? Если я использую формальный протокол, я могу просто использовать [delegate myMethod]
?
4 ответа
Вы используете его в основном только тогда, когда считаете необходимым: проверить, реализует ли объект метод, который вы собираетесь вызвать. Обычно это делается, когда у вас есть дополнительные методы или неофициальный протокол.
Я только когда-либо использовал respondsToSelector
когда я пишу код, который должен общаться с объектом делегата.
if ([self.delegate respondsToSelector:@selector(engineDidStartRunning:)]) {
[self.delegate engineDidStartRunning:self];
}
Вы иногда хотели бы использовать respondsToSelector
на любой метод, который возвращает и id
или общий NSObject
где вы не уверены, каков класс возвращаемого объекта.
Просто чтобы добавить к тому, что сказал @kubi, в другой раз я использую его, когда метод был добавлен в уже существующий класс в более новой версии фреймворков, но мне все еще нужно быть обратно совместимым. Например:
if ([myObject respondsToSelector:@selector(doAwesomeNewThing)]) {
[myObject doAwesomeNewThing];
} else {
[self doOldWorkaroundHackWithObject:myObject];
}
Как упоминалось Куби 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 подумает, что это небезопасно.
Старый вопрос, но я научился быть очень осторожным с использованием таких вещей, как addTarget:@selector(fu:), потому что имя метода не проверяется и не включается в рефакторинг XCODE. Это уже доставило мне немало хлопот. Так что теперь я сделал привычкой всегда встраивать такие вещи, как addTarget или addObserver в responsedsToSelector-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.