ios 当使用respondsToSelector在Objective-C

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3697058/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 17:42:43  来源:igfitidea点击:

when to use respondsToSelector in objective-c

objective-cios

提问by Taho

- (void)someMethod
{
    if ( [delegate respondsToSelector:@selector(operationShouldProceed)] )
    {
        if ( [delegate operationShouldProceed] )
        {
            // do something appropriate
        }
    }
}

The documentationsays:

文件说:

The precaution is necessary only for optional methods in a formal protocol or methods of an informal protocol

预防措施仅对正式协议中的可选方法或非正式协议的方法是必要的

What does it mean? If I use a formal protocol I can just use [delegate myMethod]?

这是什么意思?如果我使用正式协议,我可以使用[delegate myMethod]?

回答by kubi

You use it pretty much just when you think you need to: to check to see if an object implements the method you are about to call. Usuallythis is done when you have an optional methods or an informal protocol.

您几乎只在您认为需要时使用它:检查对象是否实现了您将要调用的方法。通常这是在您有可选方法或非正式协议时完成的。

I've only ever used respondsToSelectorwhen I'm writing code that must communicate with a delegate object.

我只respondsToSelector在编写必须与委托对象通信的代码时使用。

if ([self.delegate respondsToSelector:@selector(engineDidStartRunning:)]) {
        [self.delegate engineDidStartRunning:self];
    }

You sometimes would want to use respondsToSelectoron any method that returns and idor generic NSObjectwhere you aren't sure what the class of the returned object is.

在不确定返回对象的类是什么的情况下,您有时会希望respondsToSelector在任何返回和/id或泛型的方法上使用NSObject

回答by Dave DeLong

Just to add to what @kubi said, another time I use it is when a method was added to a pre-existing class in a newer version of the frameworks, but I still need to be backwards-compatible. For example:

只是补充一下@kubi 所说的,我另一次使用它是在较新版本的框架中将方法添加到预先存在的类时,但我仍然需要向后兼容。例如:

if ([myObject respondsToSelector:@selector(doAwesomeNewThing)]) {
  [myObject doAwesomeNewThing];
} else {
  [self doOldWorkaroundHackWithObject:myObject];
}

回答by Robert

As kubi mentioned respondsToSelectoris normally used when you have a an instance of a method that conforms to a protocol.

正如提到的 kubirespondsToSelector通常在您拥有符合协议的方法实例时使用。

// Extend from the NSObject protocol so it is safe to call `respondsToSelector` 
@protocol MyProtocol <NSObject> 

// @required by default
- (void) requiredMethod;

@optional

- (void)optionalMethod;

@end

Given and instance of this protocol we can safely call any required method.

鉴于此协议的实例,我们可以安全地调用任何所需的方法。

id <MyProtocol> myObject = ... 
[myObject requiredMethod];

However, optional methods may or may not be implemented, so you need to check at runtime.

但是,可选方法可能会也可能不会实现,因此您需要在运行时进行检查。

if ([myObject respondsToSelector:@selector(optionalMethod)]) 
{
     [myObject optionalMethod];
}

Doing this will prevent a crash with an unrecognised selector.

这样做将防止无法识别的选择器崩溃。



Also, the reason why you should declare protocols as an extension of NSObjects, i.e.

此外,您应该将协议声明为 NSObjects 的扩展的原因,即

@protocol MyProtocol <NSObject> 

Is because the NSObject protocol declares the respondsToSelector:selector. Otherwise XCode would think that it is unsafe to call it.

就是因为NSObject的协议声明的respondsToSelector:选择。否则 XCode 会认为调用它是不安全的。

回答by Wirsing

Old question, but I have learned to be very cautios with using stuff like addTarget:@selector(fu:) because the method name is not checked nor included in refactoring by XCODE. This has caused me quite some trouble already. So now I made it a habbit to always embed stuff like addTarget or addObserver in a respondsToSelector-Check like so:

老问题,但我已经学会了使用诸如 addTarget:@selector(fu:) 之类的东西要非常谨慎,因为 XCODE 未检查或包含在重构中的方法名称。这已经给我带来了一些麻烦。所以现在我习惯了总是将 addTarget 或 addObserver 之类的东西嵌入到 RespondsToSelector-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);
} 

I know its not super elegant, but i'd rather add some boilerplate code than have an unexpected crash of my apps in the App Store.

我知道它不是超级优雅,但我宁愿添加一些样板代码,也不愿让我的应用程序在 App Store 中意外崩溃。