TL;DR -> 滚动到底部
在尝试使用 Swift 面向协议编程来标记 Apple 时,我在尝试实现类之间的委托模式时偶然发现了以下问题。
我将从这个例子开始:
protocol PhotoHandlerParent {}
class UIViewController {}
class MyViewController: UIViewController, PhotoHandlerParent {}
class PhotoHandler: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
weak var delegate: PhotoHandlerParent
}
到目前为止,一切都很好。一个实例MyViewController
会很高兴地被分配为PhotoHandler
的代表。但是假设我不仅希望委托对象符合PhotoHandlerParent
,但也要一流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:问题
运行示例代码对于这个问题,可以看到用泛型声明的类的实例并设置为UIImagePickerController
的代表永远不会被它调用。声明的对象的实例without泛型被称为UIImagePickerController
.
我最好的假设是编译器不会抱怨,因为它可以验证PhotoHandler
符合UIImagePickerControllerDelegate
。然而,在运行时,PhotoHandler
实例实际上是一个PhotoHandler<MyViewController>
实例,从而以某种方式干扰UIImagePickerController
识别其委托实际实现其协议的能力。
或者我可能错过了什么?
Cheers