Когда использовать 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.

Другие вопросы по тегам