什么是快速等效的respondsToSelector?
我GOOGLE了,但无法找出什么是swift等效于respondsToSelector:是。
这是我能find的唯一的东西( Swift替代了respondsToSelector:),但是在我的情况下不太相关,因为它检查委托的存在,我没有一个委托,我只是想检查一个新的API是否存在或者不在设备上运行,如果没有回落到以前的api版本。
如前所述,在Swift 大部分时间里,你可以用什么来实现你所需要的?
可选的解包器操作员 。 这允许你调用对象的方法,当且仅当对象存在(而不是nil
)并且方法被实现。
在仍然需要respondsToSelector:
的情况下,它仍然是NSObject
协议的一部分。
如果你在Swift中调用了obj-Ctypes的respondsToSelector:
,那么它的工作方式和你所期望的一样。 如果你在你自己的Swift类中使用它,你将需要确保你的类从NSObject
派生。
下面是一个Swift类的例子,你可以检查它是否响应一个select器:
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:")
。
没有真正的Swift替代品。
您可以通过以下方式检查:
someObject.someMethod?()
只有在对象someObject
上定义方法时,才会调用someMethod
方法,但是只能将其用于声明方法为optional
@objc
协议。
Swift本质上是一种安全的语言,所以每次你调用一个方法,Swift必须知道方法在那里。 没有运行时检查是可能的。 你不能随机的对象调用随机方法。
即使在Obj-C中,你也应该尽可能地避免这样的事情,因为它不能和ARC一起玩(ARC会触发performSelector:
警告)。
但是,当检查可用的API时,如果您正在处理NSObject
实例,则仍然可以使用respondsToSelector:
即使Swift也是如此:
@interface TestA : NSObject - (void)someMethod; @end @implementation TestA //this triggers a warning @end
var a = TestA() if a.respondsToSelector("someMethod") { a.someMethod() }
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”方法来testing一个可选的协议,如下所示:
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() }
看来你需要定义你的协议作为NSObjectProtocol的子协议…那么你会得到respondsToSelector方法
@objc protocol YourDelegate : NSObjectProtocol { func yourDelegateMethod(passObject: SomeObject) }
注意只指定@objc是不够的。 你也应该小心,实际的委托是NSObject的一个子类 – 在Swift中可能不是。
如果您正在testing的方法被定义为@objc协议中的可选方法 (听起来像您的情况),那么使用可选的链接模式:
if let result = object.method?(args) { /* method exists, result assigned, use result */ } else { ... }
当方法声明为返回Void
,只需使用:
if object.method?(args) { ... }
看到:
“通过可选链接调用方法”
摘自:苹果公司“Swift编程语言”
iBooks的。 https://itun.es/us/jEUH0.l
函数是Swift中的第一类types,所以你可以通过比较它来检查一个协议中定义的可选函数是否实现了:
if (someObject.someMethod != nil) { someObject.someMethod!(someArgument) } else { // do something else }
在Swift 2中,Apple引入了一个名为API availability checking
的新function,可能是对respondsToSelector:
API availability checking
的替代。下面的代码片段比较是从WWDC2015 Session 106复制的 ,我认为可能会对您有所帮助,请检查如果你需要了解更多
旧方法:
@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 } }
目前(Swift 2.1),你可以使用3种方法检查它:
- 使用由@Erik_at_Digit回答的respondsToSelector
-
使用'?' 回答@苏尔坦
-
并
as?
运营商:if let delegateMe = self.delegate as? YourCustomViewController { delegateMe.onSuccess() }
基本上取决于你想要达到的目标:
- 例如,如果你的应用程序逻辑需要执行一些操作,并且委托没有设置,或者指出的委托没有实现onSuccess()方法(协议方法),所以选项1和3是最好的select,但我会用选项3是Swift方式。
- 如果在委托为零或方法未执行时您不想执行任何操作,请使用选项2。
对于迅速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)") } }
我只是在一个项目中自己实现这个,看下面的代码。 正如@Christopher Pickslay所提到的,重要的是要记住,函数是头等公民,因此可以被视为可选variables。
@objc protocol ContactDetailsDelegate: class { optional func deleteContact(contact: Contact) -> NSError? } ... weak var delegate:ContactDetailsDelegate! if let deleteContact = delegate.deleteContact { deleteContact(contact) }
另一个可能的语法由swift ..
if let delegate = self.delegate, method = delegate.somemethod{ method() }
我使用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)") } }
对于swift3
如果您只是想调用该方法,请运行下面的代码。
self.delegate?.method?()
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 } } }
相当于是? 运营商:
var value: NSNumber? = myQuestionableObject?.importantMethod()
如果myQuestionableObject存在并实现它,只会调用importantMethod。