问题描述
TL; DR - >滚动到底部
在尝试使用Swift标记面向协议的编程时,我偶然发现尝试在类之间实现委托模式时出现以下问题。
In trying to tag Apple on the Protocol-Oriented Programming with Swift, I stumbled upon the following problem while trying to implement a delegation pattern between classes.
我将从这个例子开始:
protocol PhotoHandlerParent {}
class UIViewController {}
class MyViewController: UIViewController, PhotoHandlerParent {}
class PhotoHandler: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
weak var delegate: PhotoHandlerParent
}
到目前为止,这么好。 MyViewController
的实例将被快乐地分配为 PhotoHandler
的委托。但是说我不仅希望委托对象符合 PhotoHandlerParent
,而且也是类 UIViewController
。在这个特定的例子中,为了使 PhotoHandler
可以代表其父视图控制器提供和关闭 UIImagePickerController
。很像:
So far, so good. An instance of MyViewController
would be happily assigned as PhotoHandler
's delegate. But say I not only wanted the delegate object to conform to PhotoHandlerParent
, but also be of class UIViewController
. In this particular example, so that the PhotoHandler
could present and dismiss an UIImagePickerController
on behalf of its parent view controller. Much like:
protocol PhotoHandlerParent {}
class UIViewController {}
class MyViewController: UIViewController, PhotoHandlerParent {}
class PhotoHandler: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
weak var delegate: UIViewController, PhotoHandlerParent
}
不幸的是,上面的代码在Swift上无效。另一方面,Swift确实有泛型,在这种情况下可能会有所帮助。因此可以尝试:
Unfortunetely, the code above doesn't work on Swift. On the other hand though, Swift does have Generics, that may help in this case. Thus one might try:
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
的委托。没有编译错误,没有运行时错误。但是...
Now interestingly enough, an instance of MyViewController
would go back to be happily assigned as PhotoHandler
's delegate. No compile error, no runtime error. But...
TL; DR:问题
运行示例代码,可以看到使用泛型声明并设置为 UIImagePickerController
的委托从不被它调用。声明为不具有泛型的对象的实例由 UIImagePickerController
调用。
Running the sample code for this question, it's possible to see that an instance of a class declared with Generics and set as a UIImagePickerController
's delegate is never called by it. An instance of an object declared without generics is called by the UIImagePickerController
.
我的最好的假设是编译器不会投诉,因为它可以验证 PhotoHandler
符合 UIImagePickerControllerDelegate
。但是,在运行时, PhotoHandler
实例实际上是一个 PhotoHandler< MyViewController>
实例,从而以某种方式干扰 UIImagePickerController
能够识别其代理实际实现其协议。
My best assumption is that the compiler doesn't complain because it can verify that PhotoHandler
conforms to UIImagePickerControllerDelegate
. However, at runtime, the PhotoHandler
instance is actually a PhotoHandler<MyViewController>
instance, thus somehow interfering with the UIImagePickerController
's ability to identify that its delegate actually implements its protocol.
或者我错过了一些可能吗?
Or am I missing something maybe?
干杯
推荐答案
从文档的角度来看,这是正确的行为,因为:
That's correct behavior from the documentation point of view, because:
回复@Bell应用实验室评论:
打开,并向下滚动到轻量级泛型。这里注意:
Open this page and scroll down to Lightweight Generics. Here's note:
它基本上说那些泛型(ObjC - > Swift)仅针对Foundation集合类进行导入,而忽略其余的操作 - 如同未进行参数化导入一样。
It basically says that generics (ObjC -> Swift) are imported only for Foundation collection classes and rest is ignored - IOW imported as if they are unparameterized.
也许我们可以期待一些改进这个地区在未来,但我怀疑。
Maybe we can expect some improvement in this area in the future, but I doubt it.
这篇关于Swift泛型和协议不能在UIKit上工作[可能的错误]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!