swift - 将*通用*协议(protocol)桥接到 Objective-C 的解决方法?

标签 swift objective-c-runtime

假设我们有以下 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/

相关文章:

ios - UINavigationController 转换委托(delegate)

ios - 修改 Collection View 单元格内容的图层属性

objective-c - 是否能够重写 NSObject init 方法以将每个对象添加到单个 NSMutableArray 中?

ios - 将浮点变量作为参数传递

ios - MapKit自动布局约束问题

ios - 确定 JSON 中的 "nil"值

objective-c - 什么决定了解决未实现方法的过程?

objective-c - Objective-C 运行时如何检索类和方法的列表?

arrays - Swift Array.contains() 不调用 PFUser 子类的 Equatable 函数

swift - 不能继承 DispatchGroup - "only visible via the Objective-C runtime"吗?