我用Google搜索但未能找到与respondsToSelector:
相当的快捷方式。
这是我能找到的唯一的东西(Swift alternative to respondsToSelector:),但在我的情况下,由于检查代表的存在,我没有太多相关性,我没有代表我只是想要在设备上运行时检查是否存在新API,如果没有,则回退到先前版本的api。
答案 0 :(得分:159)
如上所述,在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:")
相同。
答案 1 :(得分:59)
没有真正的Swift替代品。
您可以通过以下方式检查:
someObject.someMethod?()
仅当方法someMethod
在对象someObject
上定义时调用方法@objc
,但您只能将其用于已声明方法为optional
的{{1}}协议。
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()
}
答案 2 :(得分:34)
更新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()
}
原始回答:
你可以使用"如果让"测试这样的可选协议的方法:
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()
}
答案 3 :(得分:11)
您似乎需要将协议定义为NSObjectProtocol的子协议...然后您将获得respondsToSelector方法
@objc protocol YourDelegate : NSObjectProtocol
{
func yourDelegateMethod(passObject: SomeObject)
}
请注意,仅指定@objc是不够的。你应该小心实际的委托是NSObject的子类 - 在Swift中可能不是。
答案 4 :(得分:10)
如果您正在测试的方法在 @objc 协议中定义为可选方法(听起来像您的情况),那么使用可选链接模式为:
if let result = object.method?(args) {
/* method exists, result assigned, use result */
}
else { ... }
当方法声明为返回Void
时,只需使用:
if object.method?(args) { ... }
请参阅:
“通过可选链接调用方法”
摘录自:Apple Inc.“The Swift Programming Language。”
iBooks的。 https://itun.es/us/jEUH0.l
答案 5 :(得分:9)
函数是Swift中的第一类类型,因此您可以通过将它与nil进行比较来检查协议中定义的可选函数是否已实现:
if (someObject.someMethod != nil) {
someObject.someMethod!(someArgument)
} else {
// do something else
}
答案 6 :(得分:7)
在Swift 2中,Apple引入了一项名为API availability checking
的新功能,该功能可能是respondsToSelector:
方法的替代品。以下代码段比较是从WWDC2015会话106 What's New in 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
}
}
答案 7 :(得分: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)")
}
}
答案 8 :(得分:5)
如果您只想调用该方法,请运行以下代码。
self.delegate?.method?()
答案 9 :(得分:4)
目前(Swift 2.1)你可以用3种方式检查它:
使用@ {Sulthan
并使用as?
运算符:
if let delegateMe = self.delegate as? YourCustomViewController
{
delegateMe.onSuccess()
}
基本上取决于你想要达到的目标:
答案 10 :(得分:2)
我在项目中自己实现,请参阅下面的代码。正如@Christopher Pickslay所提到的,重要的是要记住,函数是一等公民,因此可以被视为可选变量。
@objc protocol ContactDetailsDelegate: class {
optional func deleteContact(contact: Contact) -> NSError?
}
...
weak var delegate:ContactDetailsDelegate!
if let deleteContact = delegate.deleteContact {
deleteContact(contact)
}
答案 11 :(得分:2)
swift的另一种可能的语法..
if let delegate = self.delegate, method = delegate.somemethod{
method()
}
答案 12 :(得分:1)
当我开始将旧项目更新为Swift 3.2时,我只需要从
更改方法respondsToSelector(selector)
为:
responds(to: selector)
答案 13 :(得分:0)
我猜您想为委托创建默认实现。您可以这样做:
let defaultHandler = {}
(delegate?.method ?? defaultHandler)()
答案 14 :(得分:0)
我使用SELECT ... INTO OUTFILE
,因此如果未实现委托功能,可以执行一些默认操作。
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"sync"
)
func main() {
rawJson := []byte(`{
"Foo": {
"Bar": "Baz"
}
}`)
bzip2Reader := bytes.NewReader(rawJson) // this stands in for the bzip2.NewReader
var wg sync.WaitGroup
wg.Add(2)
r, w := io.Pipe()
go func() {
// write everything into the pipe. Decompression happens in this goroutine.
io.Copy(w, bzip2Reader)
w.Close()
wg.Done()
}()
decoder := json.NewDecoder(r)
go func() {
for {
t, err := decoder.Token()
if err != nil {
break
}
fmt.Println(t)
}
wg.Done()
}()
wg.Wait()
}
答案 15 :(得分:-1)
斯威夫特3:
协议
class SomeObject : NSObject {
weak var delegate:SomeObject?
func delegateMethod() {
if let delegateMethod = delegate?.method{
delegateMethod()
}else {
//Failed
}
}
}
对象
{{1}}
答案 16 :(得分:-4)
相当于?操作者:
var value: NSNumber? = myQuestionableObject?.importantMethod()
只有myQuestionableObject存在并实现它才会调用importantMethod。