Подтвердить что ты не робот

Objective-C отвечаетSoSelector

Из того, что я узнал до сих пор: в Objective-C вы можете отправить любое сообщение любому объекту. Если объект реализует правильный метод, он будет выполнен, иначе ничего не произойдет. Это происходит потому, что до отправки сообщения Objective-C будет выполнять отвечаетSoSelector.

Надеюсь, я до сих пор прав.

Я сделал небольшую программу для тестирования, где действие вызывается каждый раз при перемещении ползунка. Также для тестирования я установил отправителя NSButton, но на самом деле это NSSlider. Теперь я спросил объект, будет ли он отвечать на setAlternateTitle. Пока NSButton будет делать, а NSSlider - нет. Если я запустил код и сам сделаю отвечаетSoSelector, он скажет мне, что объект не будет отвечать на этот селектор. Если я проведу что-то вроде intValue, он ответит. Так что мой код до сих пор хорош.

- (IBAction)sliderDidMove:(id)sender
{
    NSButton *slider = sender;

    BOOL responds =
    [slider respondsToSelector:@selector(setAlternateTitle)];

    if(responds == YES)
    {
        NSLog(@"YES");        
    }
    else
    {
        NSLog(@"NO");
    }

    [slider setAlternateTitle:@"Hello World"];
}

Но когда я действительно отправляю сообщение setAlternateTitle, программа выйдет из строя, и я не совсем уверен, почему. Должна ли она отвечать на запросSolector перед отправкой сообщения?

4b9b3361

Ответ 1

Прежде всего, имя метода (его селектор) включает в себя все подчасти и символы двоеточия, как указано в mvds.

Во-вторых, метод -respondsToSelector: не вызывается средой выполнения, которую обычно вызывает пользователь (самостоятельно или API, которые хотят знать, отвечает ли делегат на необязательный метод протокола).

Когда вы отправляете сообщение объекту, среда выполнения будет искать реализацию метода в классе объекта (через указатель объекта isa). Это эквивалентно отправке -respondsToSelector:, хотя само сообщение не отправляется. Если реализация метода найдена в классе или в его суперклассах, он вызывает все аргументы, которые вы передали.

Если нет, то время выполнения дает сообщение второй шанс выполнить. Он начнется с отправки сообщения + (BOOL)resolveInstanceMethod:(SEL)name классу объекта: этот метод позволяет добавить метод во время выполнения к классу: если это сообщение возвращает ДА, это означает, что он может повторно отправить сообщение.

Если это не дает сообщению третий шанс выполнить, он отправляет - (id)forwardingTargetForSelector:(SEL)aSelector с помощью селектора, этот метод может возвращать другой объект, который может отвечать на селектор от имени фактического получателя, если возвращенный объект может ответить, метод выполняется, и значение возвращается, как если бы оно было возвращено исходным сообщением. (Примечание: это доступно, начиная с OS X 10.6 или iOS 4.)

Если возвращаемый объект равен nil или self (чтобы избежать бесконечных циклов), среда выполнения дает четвертому шансу выполнить этот метод... Он отправляет сообщение - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector для получения подписи метода для создания вызова. Если один из них предоставляется, вызов отправляется через сообщение - (void)forwardInvocation:(NSInvocation *)anInvocation. В этом методе вы можете анализировать вызов и создавать другие сообщения для отправки другим целевым объектам любым способом, а затем вы можете установить возвращаемое значение вызова... Это значение будет действовать как возвращаемое значение исходного сообщения.

Наконец, если объект-объект не возвращается, то среда выполнения отправляет сообщение - (void)doesNotRecognizeSelector:(SEL)aSelector вашему объекту, реализация этого метода в классе NSObject вызывает исключение.

Ответ 2

С одной стороны, selector является не только "именем" сообщения, но и следующим, т.е. аргументами и их именами.

Таким образом, правильный селектор для некоторого -(void)setAlternateTitle:(NSString*)str будет

@selector(setAlternateTitle:)

с :

Что касается вашей проблемы: если класс respondsToSelector() и вы выполняете этот селектор, вы не должны получить сбой при отправке неизвестного селектора. Какой вид журнала сбоев вы видите в окне отладки?

(ps. почему бы не включить [slider setAlternateTitle:...] в условный блок if ( responds ) { ... }?)

Ответ 3

"Это потому, что до того, как сообщение отправленный Objective-C будет выполнять respondsToSelector".

Я думаю, это неверно. Если объект не отвечает на селектор, он будет аварийно завершен во время выполнения. Система не осуществляет автоматическую проверку. Если в системе времени выполнения была проверка, мы никогда не должны получать исключение "непризнанный селектор, отправленный в экземпляр".

Пожалуйста, сделайте меня правильным, если я ошибаюсь.

РЕДАКТИРОВАТЬ: Это не прямой сбой, но по умолчанию результат будет завершен. Вся последовательность уже объясняется в комментарии и другом ответе, поэтому я больше не буду писать это.

Ответ 4

Существует метод +instancesRespondToSelector:. Как следует из названия, он сообщает вам, реализуют ли экземпляры класса этот метод.