我在谷歌上搜索了一下,但没有找到与respondsToSelector:等价的swift:是什么。

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


当前回答

在Swift 2中,苹果引入了一个叫做API可用性检查的新功能,它可能是respondsToSelector:方法的替代品。下面的代码片段比较摘自WWDC2015第106次会议“Swift有什么新”,我想这可能会对你有所帮助,如果你需要了解更多,请查看。

老方法:

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

更好的方法:

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

其他回答

如果你要测试的方法在@objc协议中被定义为可选方法(听起来像你的情况),那么使用可选的链接模式为:

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

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

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

See:

通过可选链接调用方法 摘自:苹果公司《快速编程语言》。 iBooks。https://itun.es/us/jEUH0.l

在Swift 2中,苹果引入了一个叫做API可用性检查的新功能,它可能是respondsToSelector:方法的替代品。下面的代码片段比较摘自WWDC2015第106次会议“Swift有什么新”,我想这可能会对你有所帮助,如果你需要了解更多,请查看。

老方法:

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

更好的方法:

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

我使用guard let else,如果委托func没有实现,它可以做一些默认的事情。

@objc protocol ViewController2Delegate: NSObjectProtocol {

    optional func viewController2(controller: ViewController2, didSomethingWithStringAndReturnVoid string: String)

    optional func viewController2(controller: ViewController2, didSomethingWithStringAndReturnString string: String) -> String
}

class ViewController2: UIViewController {

    weak var delegate: ViewController2Delegate?        

    @IBAction func onVoidButtonClicked(sender: AnyObject){

        if (delegate != nil && delegate!.respondsToSelector(Selector("viewController2:didSomethingWithStringAndReturnVoid:"))) {
            NSLog("ReturnVoid is implemented")

            delegate!.viewController2!(self, didSomethingWithStringAndReturnVoid: "dummy")
        }
        else{
            NSLog("ReturnVoid is not implemented")
            // Do something by default
        }
    }

    @IBAction func onStringButtonClicked(sender: AnyObject){

        guard let result = delegate?.viewController2?(self, didSomethingWithStringAndReturnString: "dummy") else {
            NSLog("ReturnString is not implemented")
            // Do something by default
            return
        }

        NSLog("ReturnString is implemented with result: \(result)")
    }
}

我只是在一个项目中实现了这一点,见下面的代码。正如@Christopher Pickslay提到的,重要的是要记住函数是第一类公民,因此可以像可选变量一样对待。

@objc protocol ContactDetailsDelegate: class {

    optional func deleteContact(contact: Contact) -> NSError?
}

...

weak var delegate:ContactDetailsDelegate!

if let deleteContact = delegate.deleteContact {
    deleteContact(contact)
}

如前所述,在Swift中,大多数情况下您可以通过?可选的解包装操作符。这允许你当且仅当对象存在(不是nil)并且方法被实现时调用该对象的方法。

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

如果你在Swift的Obj-C类型上调用respondsToSelector:,那么它的工作原理与你所期望的一样。如果你在你自己的Swift类上使用它,你需要确保你的类派生自NSObject。

下面是一个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

重要的是不要遗漏参数名。在本例中,Selector("sleep::")与Selector("sleep:minutes:")不同。