我在谷歌上搜索了一下,但没有找到与respondsToSelector:等价的swift:是什么。
这是我唯一能找到的(Swift替代respondsToSelector),但在我的情况下并不太相关,因为它检查委托的存在,我没有委托,我只是想检查在设备上运行时是否存在新的API,如果没有回落到API的以前版本。
我在谷歌上搜索了一下,但没有找到与respondsToSelector:等价的swift:是什么。
这是我唯一能找到的(Swift替代respondsToSelector),但在我的情况下并不太相关,因为它检查委托的存在,我没有委托,我只是想检查在设备上运行时是否存在新的API,如果没有回落到API的以前版本。
当前回答
如果你要测试的方法在@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替代品。
您可以通过以下方式进行检查:
someObject.someMethod?()
只有当someemethod方法定义在对象someObject上时,才会调用它,但你只能将它用于已声明该方法为可选的@objc协议。
Swift本质上是一种安全的语言,所以每次你调用一个方法时,Swift都必须知道这个方法在那里。不可能进行运行时检查。你不能对随机对象调用随机方法。
即使在Obj-C中,你也应该尽可能避免这样的事情,因为它不能很好地使用ARC (ARC会触发performSelector的警告:)。
然而,当检查可用的api时,你仍然可以使用respondsToSelector:,即使是Swift,如果你正在处理NSObject实例:
@interface TestA : NSObject
- (void)someMethod;
@end
@implementation TestA
//this triggers a warning
@end
var a = TestA()
if a.respondsToSelector("someMethod") {
a.someMethod()
}
我只是在一个项目中实现了这一点,见下面的代码。正如@Christopher Pickslay提到的,重要的是要记住函数是第一类公民,因此可以像可选变量一样对待。
@objc protocol ContactDetailsDelegate: class {
optional func deleteContact(contact: Contact) -> NSError?
}
...
weak var delegate:ContactDetailsDelegate!
if let deleteContact = delegate.deleteContact {
deleteContact(contact)
}
等价的是?接线员:
var value: NSNumber? = myQuestionableObject?.importantMethod()
importantMethod只在myQuestionableObject存在并实现它时才会被调用。
我猜你想为委托做一个默认实现。你可以这样做:
let defaultHandler = {}
(delegate?.method ?? defaultHandler)()
在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
}
}