什么是Swift等效的respondsToSelector?

Gru*_*kes 189 objective-c selector swift

我用谷歌搜索,但无法找出快速等同于什么respondsToSelector:.

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

Eri*_*rik 163

如上所述,在Swift中,大多数情况下,您可以通过?可选的unwrapper运算符实现所需的功能.这允许您在对象上调用方法,当且仅当对象存在(而不是nil)并且方法已实现时.

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

如果您respondsToSelector:在Swift 中调用Obj-C类型,那么它的工作方式与您期望的相同.如果您在自己的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
Run Code Online (Sandbox Code Playgroud)

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

  • 你需要拆分那些行*或*删除`let x =`部分.基本上,`if let x = y`结构是解包可选值(类似于`!`).因为你从`respondsToSelector`得到一个`Bool`,编译器抱怨结果不是一个可选类型(`Bool?`). (4认同)

Sul*_*han 59

没有真正的Swift替代品.

您可以通过以下方式办理登机手续:

someObject.someMethod?()
Run Code Online (Sandbox Code Playgroud)

someMethod只有在对象上定义了方法,才会调用该方法,someObject但只能将其用于@objc已声明方法的协议optional.

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

即使在Obj-C中你也应该尽可能避免使用这些东西,因为它与ARC不能很好地结合(ARC会触发警告performSelector:).

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

@interface TestA : NSObject

- (void)someMethod;

@end

@implementation TestA

//this triggers a warning

@end   
Run Code Online (Sandbox Code Playgroud)


var a = TestA()

if a.respondsToSelector("someMethod") {
   a.someMethod()
}
Run Code Online (Sandbox Code Playgroud)


hyo*_*uuu 35

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

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

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

weak var delegate: SomeDelegateWithOptionals?

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

原始答案:

您可以使用"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()
}
Run Code Online (Sandbox Code Playgroud)

  • 如果让theMethod =委托?.OptionalProtocolMethod (4认同)
  • 有多个候选时的选择器语法示例:`let theMethod = delegate.userNotificationCenter(_:willPresent:withCompletionHandler:)` (3认同)

Mat*_*mar 11

您似乎需要将协议定义为NSObjectProtocol的子协议...然后您将获得respondsToSelector方法

@objc protocol YourDelegate : NSObjectProtocol
{
    func yourDelegateMethod(passObject: SomeObject)
}
Run Code Online (Sandbox Code Playgroud)

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


GoZ*_*ner 10

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

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

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

if object.method?(args) { ... }
Run Code Online (Sandbox Code Playgroud)

看到:

"通过可选链接调用方法"
摘录自:Apple Inc."The Swift Programming Language."
iBooks.https://itun.es/us/jEUH0.l


Chr*_*lay 9

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

if (someObject.someMethod != nil) {
    someObject.someMethod!(someArgument)
} else {
    // do something else
}
Run Code Online (Sandbox Code Playgroud)

  • 如果方法重载怎么办?我们如何检查特定的? (2认同)

tou*_*bun 7

在Swift 2中,Apple引入了一个名为的新功能API availability checking,它可能是respondsToSelector:方法的替代品.以下代码片段比较是从WWDC2015会话106中复制的.我认为Swift的新功能可能对您有所帮助,如果您需要,请查看它知道更多.

旧方法:

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

更好的方法:

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


Jas*_* Yu 7

对于swift3

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

self.delegate?.method?()


Kak*_*shi 6

对于swift 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)")
    }
}
Run Code Online (Sandbox Code Playgroud)


chA*_*xey 5

当我开始将旧项目更新到 Swift 3.2 时,我只需要将方法从

respondsToSelector(selector)
Run Code Online (Sandbox Code Playgroud)

到:

responds(to: selector)
Run Code Online (Sandbox Code Playgroud)