在Swift中,如何在不实际调用该方法的情况下测试对象是否实现了签名不同的可选协议方法?
使用Swift,是否可以测试一个对象是否实现了一个可选的协议方法而不实际调用该方法?除了可选方法仅因其签名不同的情况外,这是有效的 考虑一下这个代码在Swift中,如何在不实际调用该方法的情况下测试对象是否实现了签名不同的可选协议方法?,swift,protocols,optional,optional-arguments,Swift,Protocols,Optional,Optional Arguments,使用Swift,是否可以测试一个对象是否实现了一个可选的协议方法而不实际调用该方法?除了可选方法仅因其签名不同的情况外,这是有效的 考虑一下这个代码 @objc public protocol TestDelegate : AnyObject { @objc optional func testx() @objc optional func test(with string:String) @objc optional func test(with2 int:Int) }
@objc public protocol TestDelegate : AnyObject {
@objc optional func testx()
@objc optional func test(with string:String)
@objc optional func test(with2 int:Int)
}
let delegate:TestDelegate? = nil
if let _ = delegate?.test(with:) {
print("supports 'test(with:)'")
}
if let _ = delegate?.testx {
print("supports 'testx'")
}
如果您将上面的内容粘贴到操场上,它将按预期工作
但是,如果将testx
更改为test
,它将不再工作
同样,如果您将test(with2)
更改为test(with)
,那么这也不会起作用
有没有办法测试那些只因签名不同而不同的方法?嘿,MarqueIV,检查您可以使用的可选内置函数 func响应(对选择器:选择器!)->Bool 返回一个布尔值,该值指示接收方是否实现或继承可以响应指定消息的方法 应用程序负责确定错误响应是否应被视为错误 无法通过使用super关键字向对象发送响应(to:)来测试对象是否从其超类继承方法 此方法仍将作为一个整体测试对象,而不仅仅是测试超类的实现 因此,将响应(to:)发送到super相当于将其发送到self 相反,您必须直接在对象的超类上调用NSObject类方法InstancesResponse(to:),如下面的代码片段所示 清单1
if( [MySuperclass instancesRespondToSelector:@selector(aMethod)] ) {
// invoke the inherited method
[super aMethod];
}
您不能简单地使用[[self superclass]instanceRespondtoSelector:@selector(aMethod)],因为如果子类调用该方法,则可能会导致该方法失败
请注意,如果接收方能够将选择器消息转发给另一个对象,那么它将能够响应消息,尽管是间接的,即使此方法返回false也是如此。
参数选择器
标识消息的选择器。 退换商品 如果接收方实现或继承了可以响应选择器的方法,则为true,否则为false。 SDKs iOS 2.0+、macOS 10.0+、tvOS 9.0+、watchOS 2.0+如中所示,您可以显式强制函数引用其预期类型,以解决此类歧义 唯一的区别是,由于此类函数引用是通过可选链接执行的
@optional
协议要求,因此需要强制使用可选类型的函数。从那里,您可以与nil
进行比较,以确定两个委托是否都是非nil的,并且它实现了给定的需求
例如:
import Foundation
@objc public protocol TestDelegate : AnyObject {
@objc optional func test()
// Need to ensure the requirements have different selectors.
@objc(testWithString:) optional func test(with string: String)
@objc(testWithInt:) optional func test(with int: Int)
}
class C : TestDelegate {
func test() {}
func test(with string: String) {}
func test(with string: Int) {}
}
var delegate: TestDelegate? = C()
if delegate?.test as (() -> Void)? != nil {
print("supports 'test'")
}
if delegate?.test(with:) as ((String) -> Void)? != nil {
print("supports 'test w/ String'")
}
if delegate?.test(with:) as ((Int) -> Void)? != nil {
print("supports 'test w/ Int'")
}
// supports 'test'
// supports 'test w/ String'
// supports 'test w/ Int'
请注意,我给了
测试(带有:)
需求唯一的选择器,以确保它们不会冲突(这不会影响消歧,只允许类C
符合TestDelegate
)。比较–您可以显式强制消除所需的重载,例如delegate?。测试为(()->Void)?
。有趣。我试过了(还有一些变体)无法让它工作。让我再试一次。你能提供更多的上下文来说明你想用这个解决什么吗?这似乎是一个XY问题。没有什么需要“解决”的问题。只是学习更多关于语言的知识。上面的内容只是从我正在玩的一个操场上剪下来的。@Hamish,我似乎无法得到你关于2n的答案d以上的大小写(参数名称相同,但类型不同。)这可能吗?非常有知识!如果我错了,请纠正我,但那是Objective-C。我的问题是专门针对Swift的,而这是不可用的。@MarqueIV此解释是Objective-C,但我用粗体字母写的方法是Swift,请检查,Xcode将自动建议它。手动调用响应(to:)
IMO并不是一种惯用的快速检查类实例是否实现了@optional
协议要求的方法。此类引用返回可选函数以模拟一致性类可能没有实现它们的事实。