Swift 泛型和协议不适用于 UIKit [可能的错误]

Swift Generics and Protocols not working on UIKit [possible bug]

TL;DR -> 滚动到底部

在尝试使用 Swift 在面向协议的编程中标记 Apple 时,我在尝试在 class 之间实现委托模式时偶然发现了以下问题。

我将从这个例子开始:

protocol PhotoHandlerParent {}

class UIViewController {}

class MyViewController: UIViewController, PhotoHandlerParent {}

class PhotoHandler: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    weak var delegate: PhotoHandlerParent
}

到目前为止,还不错。 MyViewController 的一个实例将被愉快地指定为 PhotoHandler 的委托。但是假设我不仅希望委托对象符合 PhotoHandlerParent,而且还符合 class UIViewController。在此特定示例中,PhotoHandler 可以代表其父视图控制器呈现和关闭 UIImagePickerController。很像:

protocol PhotoHandlerParent {}

class UIViewController {}

class MyViewController: UIViewController, PhotoHandlerParent {}

class PhotoHandler: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    weak var delegate: UIViewController, PhotoHandlerParent
}

不幸的是,上面的代码不适用于 Swift。另一方面,Swift 确实有泛型,这在这种情况下可能会有所帮助。因此可以尝试:

protocol PhotoHandlerParent {}

class UIViewController {}

class MyViewController: UIViewController, PhotoHandlerParent {}

class PhotoHandler<Parent where Parent: UIViewController, Parent: PhotoHandlerParent>: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    weak var delegate: Parent
}

现在有趣的是,MyViewController 的一个实例将返回并愉快地分配为 PhotoHandler 的委托。没有编译错误,没有运行时错误。但是...

TL;DR:问题

运行 sample code 对于这个问题,可以看到 class 的一个实例用泛型声明并设置为 UIImagePickerController 的委托是从来没有被它调用过。 没有 泛型的对象实例被 UIImagePickerController.

调用

我最好的假设是编译器不会抱怨,因为它可以验证 PhotoHandler 是否符合 UIImagePickerControllerDelegate。然而,在运行时,PhotoHandler 实例实际上是一个 PhotoHandler<MyViewController> 实例,因此以某种方式干扰了 UIImagePickerController 识别其委托实际实现其协议的能力。

还是我漏掉了什么?

干杯

从文档的角度来看,这是正确的行为,因为:

Method in a generic class cannot be represented in Objective-C


回复@Bell App Lab评论:

打开 this page 并向下滚动到 轻量级泛型 。注意事项:

Aside from than these Foundation collection classes, Objective-C lightweight generics are ignored by Swift. Any other types using lightweight generics are imported into Swift as if they were unparameterized.

它基本上是说泛型 (ObjC -> Swift) 仅为 Foundation 集合导入 类 其余部分将被忽略 - IOW 导入时就好像它们没有参数化一样。

也许我们可以期待未来在这方面有所改进,但我对此表示怀疑。