本文介绍了Swift泛型和协议不能在UIKit上工作[可能的错误]的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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上工作[可能的错误]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-28 03:57