Objective c Swift与respondsToSelector的等价物是什么?
我在谷歌上搜索过,但没能找到swift与响应选择器:的等价物Objective c Swift与respondsToSelector的等价物是什么?,objective-c,swift,selector,Objective C,Swift,Selector,我在谷歌上搜索过,但没能找到swift与响应选择器:的等价物 这是我能找到的唯一一件事(),但在我的情况下并不太相关,因为它检查委托的存在,我没有委托,我只是想检查在设备上运行时是否存在新的API,如果没有,则返回到以前版本的API。没有真正的快速替换 您可以通过以下方式进行检查: someObject.someMethod?() 只有在对象someObject上定义了方法someMethod时,才会调用方法someMethod,但您只能将其用于声明方法为可选的@objc协议 Swift本质上
这是我能找到的唯一一件事(),但在我的情况下并不太相关,因为它检查委托的存在,我没有委托,我只是想检查在设备上运行时是否存在新的API,如果没有,则返回到以前版本的API。没有真正的快速替换 您可以通过以下方式进行检查:
someObject.someMethod?()
只有在对象someObject
上定义了方法someMethod
时,才会调用方法someMethod
,但您只能将其用于声明方法为可选的@objc
协议
Swift本质上是一种安全的语言,因此每次调用方法时,Swift都必须知道该方法存在。不可能进行运行时检查。你不能只对随机对象调用随机方法
即使在Obj-C中,您也应该尽可能避免这些事情,因为它不能很好地使用ARC(ARC随后会触发性能选择器的警告:
)
但是,在检查可用的API时,如果您处理的是NSObject
实例,则即使使用Swift,您仍然可以使用respondsToSelector:
:
@interface TestA : NSObject
- (void)someMethod;
@end
@implementation TestA
//this triggers a warning
@end
等价物是?接线员:
var value: NSNumber? = myQuestionableObject?.importantMethod()
if let delegateMe = self.delegate as? YourCustomViewController
{
delegateMe.onSuccess()
}
仅当MyQuestibleObject存在并实现它时,才会调用importantMethod。如前所述,在Swift中,大多数情况下,您可以使用?
可选的展开器操作符来实现所需。这允许您在且仅当对象存在(而不是nil
)且方法已实现时,对对象调用方法
@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)")
}
}
如果仍然需要响应选择器:
,它仍然作为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:”)
不同,如果您测试的方法被定义为@objc协议中的可选方法(听起来像您的案例),则使用可选的链接模式如下:
if let result = object.method?(args) {
/* method exists, result assigned, use result */
}
else { ... }
当该方法声明为返回Void
时,只需使用:
if object.method?(args) { ... }
见:
“通过可选链接调用方法”
摘自:苹果公司的《Swift编程语言》。
我的书
似乎您需要将您的协议定义为NSObjectProtocol的子协议。。。然后您将得到respondsToSelector方法
@objc protocol YourDelegate : NSObjectProtocol
{
func yourDelegateMethod(passObject: SomeObject)
}
请注意,仅指定@objc是不够的。您还应注意,实际委托是NSObject的一个子类,而在Swift中可能不是。更新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()
}
原始答案:
您可以使用“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()
}
函数是Swift中的一级类型,因此您可以通过将协议中定义的可选函数与nil进行比较来检查该函数是否已实现:
if (someObject.someMethod != nil) {
someObject.someMethod!(someArgument)
} else {
// do something else
}
我只是在一个项目中自己实现这个,请参见下面的代码。正如@Christopher Pickslay所提到的,重要的是要记住函数是一级公民,因此可以被视为可选变量
@objc protocol ContactDetailsDelegate: class {
optional func deleteContact(contact: Contact) -> NSError?
}
...
weak var delegate:ContactDetailsDelegate!
if let deleteContact = delegate.deleteContact {
deleteContact(contact)
}
在Swift 2中,苹果公司推出了一项新功能,名为API可用性检查
,它可能会取代respondsToSelector:
方法。下面的代码片段比较是从WWDC2015会话106复制的,我认为这可能会对您有所帮助,如果您需要了解更多信息,请查看
旧方法:
更好的方法是:
swift提供的另一种可能的语法
if let delegate = self.delegate, method = delegate.somemethod{
method()
}
目前(Swift 2.1),您可以使用3种方式进行检查:
使用@Erik_在数字处回答
使用@Sulthan的回答
并使用作为
运算符:
var value: NSNumber? = myQuestionableObject?.importantMethod()
if let delegateMe = self.delegate as? YourCustomViewController
{
delegateMe.onSuccess()
}
基本上,这取决于您试图实现的目标:
- 例如,如果您的应用程序逻辑需要执行某些操作,而委托没有设置,或者指定的委托没有实现onSuccess()方法(协议方法),那么选项1和3是最佳选择,尽管我会使用选项3,这是一种快速的方法
- 当委托为nil或方法未实现时,如果您不想执行任何操作,请使用选项2
我使用了guard let else
,这样,如果没有实现委托函数,就可以执行一些默认操作
@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)")
}
}
适用于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)")
}
}
Swift 3:
协议
@objc protocol SomeDelegate {
@objc optional func method()
}
反对
class SomeObject : NSObject {
weak var delegate:SomeObject?
func delegateMethod() {
if let delegateMethod = delegate?.method{
delegateMethod()
}else {
//Failed
}
}
}
对于swift3
如果您只想调用该方法,请运行下面的代码
self.delegate?.method?()
当我开始将我的旧项目更新为Swift 3.2时,我只需要将方法从
respondsToSelector(selector)
致:
我想您应该为委托创建一个默认实现。您可以这样做:
let defaultHandler = {}
(delegate?.method ?? defaultHandler)()
所有这些都意味着用可选的替换,并用可选的链接来执行。鉴于苹果明确建议使用NSClassFromString
和respondsToSelector
等机制来检查新实现的功能,我不得不相信这些机制要么已经到位,或者在释放前会在那里。尝试观看WWDC的高级互操作…
视频。@Jack Wu但如果新方法是在UIApplication或UIViewController等基础上引入的新方法,该怎么办。这些目标
let defaultHandler = {}
(delegate?.method ?? defaultHandler)()