【发布时间】:2018-06-26 23:12:14
【问题描述】:
假设我们有以下 Objective-C API:
- (id)foo:(Protocol *)proto;
导入到 Swift 中的是:
func foo(_ proto: Protocol) -> Any
是的,它是为我们提供代理对象的其中之一。在 Swift 中使用这些往往很烦人,所以假设我们想要对这个东西进行包装以使其更友好一些。首先我们定义了几个 Objective-C 兼容的协议:
@objc protocol Super {}
@objc protocol Sub: Super {}
现在,我们定义一个函数,它接受一个符合Super 的协议并将其传递给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 协议的东西。嗯。
问题在于,尽管Sub 符合Super 的事实意味着它必须是一个Objective-C 协议,但编译器并没有意识到这一点。我们可以解决这个问题并手动桥接它吗?好吧,我们来看看Protocol的界面,看看有没有什么可以...
OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0)
@interface Protocol : NSObject
@end
哦。嗯。
嗯,Protocol 是一个成熟的NSObject 子类这一事实表明,这可能都是我最喜欢的功能的工作,神奇的 SwiftObjective-C 桥执行非平凡的转换在事情不明显的情况下发生了什么。好吧,这至少给了我一个想法;我应该能够通过强制转换为AnyObject 来手动调用桥接器,并希望通过as! 或其他方式获得Protocol 对象。有用吗?
print(Sub.self as AnyObject) // <Protocol: 0x012345678>
嗯,这很有希望。当我在我的泛型参数上尝试它时?
print(proto as AnyObject) // Terminated due to signal: SEGMENTATION FAULT (11)
哦,来吧上。
我怀疑这可能是编译器中的一个错误,我计划测试一些东西以确定是否是这种情况,但由于 Swift 源代码需要很长时间才能编译,所以我想我会在这里发布这个我在等待。有人对这里发生的事情有任何见解和/或解决方法吗?
【问题讨论】: