objective-c 什么是 Swift 等效的 respondsToSelector?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24167791/
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-09-03 21:19:49  来源:igfitidea点击:

What is the Swift equivalent of respondsToSelector?

objective-cswiftselector

提问by Gruntcakes

I've googled but not been able to find out what the swift equivalent to respondsToSelector:is.

我用谷歌搜索但无法找出 swift 的等价物respondsToSelector:是什么。

This is the only thing I could find (Swift alternative to respondsToSelector:) but isn't too relevant in my case as its checking the existence of the delegate, I don't have a delegate I just want to check if a new API exists or not when running on the device and if not fall back to a previous version of the api.

这是我唯一能找到的(Swift 替代 RespondsToSelector:)但在我的情况下并不太相关,因为它检查委托的存在,我没有委托,我只想检查是否存在新的 API或不在设备上运行时,如果不回退到 api 的先前版本。

采纳答案by Erik

As mentioned, in Swift most of the time you can achieve what you need with the ?optional unwrapper operator. This allows you to call a method on an object if and only if the object exists (not nil) and the method is implemented.

如前所述,在 Swift 中,大多数情况下,您可以使用?可选的解包运算符来实现所需的功能。这允许您在对象上调用方法,当且仅当该对象存在(不存在nil)并且该方法已实现。

In the case where you still need respondsToSelector:, it is still there as part of the NSObjectprotocol.

在您仍然需要的情况下respondsToSelector:,它仍然作为NSObject协议的一部分存在。

If you are calling respondsToSelector:on an Obj-C type in Swift, then it works the same as you would expect. If you are using it on your own Swift class, you will need to ensure your class derives from NSObject.

如果您respondsToSelector:在 Swift中调用Obj-C 类型,那么它的工作方式与您期望的一样。如果您在自己的 Swift 类中使用它,则需要确保您的类从NSObject.

Here's an example of a Swift class that you can check if it responds to a selector:

这是一个 Swift 类的示例,您可以检查它是否响应选择器:

class Worker : NSObject
{
    func work() { }
    func eat(food: AnyObject) { }
    func sleep(hours: Int, minutes: Int) { }
}

let worker = Worker()

let canWork = worker.respondsToSelector(Selector("work"))   // true
let canEat = worker.respondsToSelector(Selector("eat:"))    // true
let canSleep = worker.respondsToSelector(Selector("sleep:minutes:"))    // true
let canQuit = worker.respondsToSelector(Selector("quit"))   // false

It is important that you do not leave out the parameter names. In this example, Selector("sleep::")is notthe same as Selector("sleep:minutes:").

重要的是不要遗漏参数名称。在这个例子中,Selector("sleep::")一样的Selector("sleep:minutes:")

回答by Sulthan

There is no real Swift replacement.

没有真正的 Swift 替代品。

You can check in the following way:

您可以通过以下方式进行检查:

someObject.someMethod?()

This calls the method someMethodonly if it's defined on object someObjectbut you can use it only for @objcprotocols which have declared the method as optional.

someMethod仅当它在对象上定义时才调用该方法,someObject但您只能将它用于@objc将该方法声明为optional.

Swift is inherently a safe language so everytime you call a method Swift has to know the method is there. No runtime checking is possible. You can't just call random methods on random objects.

Swift 本质上是一种安全的语言,所以每次你调用一个方法时,Swift 都必须知道该方法在那里。无法进行运行时检查。您不能只对随机对象调用随机方法。

Even in Obj-C you should avoid such things when possible because it doesn't play well with ARC (ARC then triggers warnings for performSelector:).

即使在 Obj-C 中,您也应该尽可能避免此类事情,因为它与 ARC 不能很好地配合使用(然后 ARC 会触发 警告performSelector:)。

However, when checking for available APIs, you can still use respondsToSelector:, even if Swift, if you are dealing with NSObjectinstances:

但是,在检查可用的 API 时respondsToSelector:,如果您正在处理NSObject实例,您仍然可以使用,即使是 Swift :

@interface TestA : NSObject

- (void)someMethod;

@end

@implementation TestA

//this triggers a warning

@end   



var a = TestA()

if a.respondsToSelector("someMethod") {
   a.someMethod()
}

回答by hyouuu

Update Mar 20, 2017 for Swift 3 syntax:

2017 年 3 月 20 日更新 Swift 3 语法:

If you don't care whether the optional method exists, just call delegate?.optionalMethod?()

如果您不在乎可选方法是否存在,只需调用 delegate?.optionalMethod?()

Otherwise, using guardis probably the best approach:

否则,使用guard可能是最好的方法:

weak var delegate: SomeDelegateWithOptionals?

func someMethod() {
    guard let method = delegate?.optionalMethod else {
        // optional not implemented
        alternativeMethod()
        return
    }
    method()
}

Original answer:

原答案:

You can use the "if let" approach to test an optional protocol like this:

您可以使用“if let”方法来测试这样的可选协议:

weak var delegate: SomeDelegateWithOptionals?

func someMethod() {
  if let delegate = delegate {
    if let theMethod = delegate.theOptionalProtocolMethod? {
      theMethod()
      return
    }
  }
  // Reaching here means the delegate doesn't exist or doesn't respond to the optional method
  alternativeMethod()
}

回答by Matej Ukmar

It seems you need to define your protocol as as subprotocol of NSObjectProtocol ... then you'll get respondsToSelector method

看来您需要将您的协议定义为 NSObjectProtocol 的子协议……然后您将获得 RespondsToSelector 方法

@objc protocol YourDelegate : NSObjectProtocol
{
    func yourDelegateMethod(passObject: SomeObject)
}

note that only specifying @objc was not enough. You should be also careful that the actual delegate is a subclass of NSObject - which in Swift might not be.

请注意,仅指定 @objc 是不够的。您还应该注意实际委托是 NSObject 的子类 - 在 Swift 中可能不是。

回答by GoZoner

If the method you are testing for is defined as an optional methodin a @objcprotocol (which sounds like your case), then use the optional chainingpattern as:

如果要用于测试所述方法被定义为一个可选的方法中一个@objc协议(这听起来像您的情况下),然后使用可选链接模式为:

if let result = object.method?(args) {
  /* method exists, result assigned, use result */
}
else { ... }

When the method is declare as returning Void, simply use:

当方法声明为返回时Void,只需使用:

if object.method?(args) { ... }

See:

看:

“Calling Methods Through Optional Chaining”
Excerpt From: Apple Inc. “The Swift Programming Language.”
iBooks. https://itun.es/us/jEUH0.l

“通过可选链调用方法”
摘自:Apple Inc. “The Swift Programming Language”。
电子书。https://itun.es/us/jEUH0.l

回答by Christopher Pickslay

Functions are first-class types in Swift, so you can check whether an optional function defined in a protocol has been implemented by comparing it to nil:

函数是 Swift 中的第一类类型,因此您可以通过将其与 nil 进行比较来检查协议中定义的可选函数是否已实现:

if (someObject.someMethod != nil) {
    someObject.someMethod!(someArgument)
} else {
    // do something else
}

回答by Jason Yu

For swift3

对于 swift3

If you just want to call the method, run the code below.

如果您只想调用该方法,请运行以下代码。

self.delegate?.method?()

self.delegate?.method?()

回答by tounaobun

In Swift 2,Apple introduced a new feature called API availability checking, which might be a replacement for respondsToSelector:method.The following code snippet comparison is copied from the WWDC2015 Session 106 What's New in Swiftwhich I thought might help you,please check it out if you need to know more.

在 Swift 2 中,Apple 引入了一个名为 的新功能API availability checking,它可能会替代respondsToSelector:method。以下代码片段比较复制自 WWDC2015 Session 106 What's New in Swift我认为可能对您有所帮助,如果您需要,请查看了解更多。

The Old Approach:

旧方法:

@IBOutlet var dropButton: NSButton!
override func awakeFromNib() {
    if dropButton.respondsToSelector("setSpringLoaded:") {
        dropButton.springLoaded = true
    }
}

The Better Approach:

更好的方法:

@IBOutlet var dropButton: NSButton!
override func awakeFromNib() {
    if #available(OSX 10.10.3, *) {
        dropButton.springLoaded = true
    }
}

回答by Kakashi

For swift 3.0

快速 3.0

import UIKit

@objc protocol ADelegate : NSObjectProtocol {

    @objc optional func hi1()
    @objc optional func hi2(message1:String, message2:String)
}

class SomeObject : NSObject {

    weak var delegate:ADelegate?

    func run() {

        // single method
        if let methodHi1 = delegate?.hi1 {
            methodHi1()
        } else {
            print("fail h1")
        }

        // multiple parameters
        if let methodHi2 = delegate?.hi2 {
            methodHi2("superman", "batman")
        } else {
            print("fail h2")
        }
    }
}

class ViewController: UIViewController, ADelegate {

    let someObject = SomeObject()

    override func viewDidLoad() {
        super.viewDidLoad()

        someObject.delegate = self
        someObject.run()
    }

    // MARK: ADelegate
    func hi1() {

        print("Hi")
    }

    func hi2(message1: String, message2: String) {

        print("Hi \(message1) \(message2)")
    }
}

回答by OhadM

Currently (Swift 2.1) you can check it using 3 ways:

目前(Swift 2.1)您可以使用 3 种方式检查它:

  1. Using respondsToSelectoranswered by @Erik_at_Digit
  2. Using '?'answered by @Sulthan

  3. And using as?operator:

    if let delegateMe = self.delegate as? YourCustomViewController
    {
       delegateMe.onSuccess()
    }
    
  1. 使用respondsToSelector回答@Erik_at_Digit
  2. 使用“?” @Sulthan 回答

  3. 并使用as?运算符:

    if let delegateMe = self.delegate as? YourCustomViewController
    {
       delegateMe.onSuccess()
    }
    

Basically it depends on what you are trying to achieve:

基本上,这取决于您要实现的目标:

  • If for example your app logic need to perform some action and the delegate isn't set or the pointed delegate didn't implement the onSuccess() method (protocol method) so option 1 and 3 are the best choice, though I'd use option 3 which is Swift way.
  • If you don't want to do anything when delegate is nil or method isn't implemented then use option 2.
  • 例如,如果您的应用程序逻辑需要执行某些操作并且未设置委托或指向的委托未实现 onSuccess() 方法(协议方法),则选项 1 和 3 是最佳选择,尽管我会使用选项 3 是 Swift 的方式。
  • 如果您不想在委托为零或未实现方法时执行任何操作,请使用选项 2。