假设我们有以下 Objective-C API:
- (id)foo:(Protocol *)proto;
导入 Swift 为:
func foo(_ proto: Protocol) -> Any
是的,它是为我们提供代理对象的那些东西之一。这些在 Swift 中使用起来往往很烦人,所以假设我们想围绕这个东西做一个包装器,让它更友好一些。首先,我们定义了几个 Objective-C 兼容的协议(protocol):
@objc protocol Super {}
@objc protocol Sub: Super {}
现在,我们定义一个函数,它接受一个符合 Super
的协议(protocol)并将其传递给 foo()
,然后我们用 Sub< 调用它
作为参数看是否有效:
func bar<P: Super>(proto: P.Type) {
let proxy = foo(proto)
// do whatever with the proxy
}
bar(proto: Sub.self)
嗯,这不编译。给出的错误信息是:
error: cannot convert value of type 'P.Type' to expected argument type 'Protocol'
这里有一些做(大部分)编译的东西:
func bar<P: Super>(proto: P.Type) {
// when called with 'Sub.self' as 'proto':
print(type(of: proto)) // Sub.Protocol
print(type(of: Sub.self)) // Sub.Protocol
print(proto == Sub.self) // true
let proxy1 = foo(Sub.self) // compiles, runs, works
let proxy2 = foo(proto) // error: cannot convert value of type 'P.Type' to expected argument type 'Protocol'
}
好的,它几乎在所有方面都与 Sub.self
相同,只是我不能将它传递给需要 Objective-C 协议(protocol)的东西。嗯。
问题是,尽管 Sub
符合 Super
的事实意味着它必须是一个 Objective-C 协议(protocol),但编译器并没有意识到这一点。我们可以解决这个问题并手动桥接它吗?好吧,让我们看一下 Protocol
的界面,看看有什么我们可以...
OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0)
@interface Protocol : NSObject
@end
哦。嗯。
好吧,Protocol
是一个成熟的 NSObject
子类这一事实表明,这可能是我最喜欢的功能,神奇的 Swift<-> Objective-C 桥,对事物执行重要的转换,而不是显而易见的事情。好吧,这至少给了我一个想法;我应该能够通过强制转换为 AnyObject
来手动调用桥,并希望以这种方式获取 Protocol
对象,也许通过 as!
或某物。有用吗?
print(Sub.self as AnyObject) // <Protocol: 0x012345678>
嗯,这很有希望。当我在我的通用参数上尝试它时?
print(proto as AnyObject) // Terminated due to signal: SEGMENTATION FAULT (11)
哦,来吧。
我怀疑这可能是编译器中的一个错误,我计划测试一些东西以确定是否是这种情况,但是由于 Swift 源代码需要一个地质时代来编译,我想我会在这里发布它我在等待。有人对这里发生的事情有任何见解和/或解决方法吗?
最佳答案
我知道它确实不漂亮,也不“敏捷”,但是可以使用 NSProtocolFromString 来获取适合传入
如下:foo
的 Objective-C Protocol
let proxy2 = foo(NSProtocolFromString(String(reflecting: proto))!)
其中 String(reflecting:)
是获取适合通过 NSProtocolFromString
解析的完全限定类型名称的有用方法。
我会说你遇到的崩溃是一个错误。
关于swift - 将*通用*协议(protocol)桥接到 Objective-C 的解决方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51052531/