我如何声明一个具有types和实现协议的variables?

我的应用程序有一个协议详细视图控制器,说明他们必须有一个viewModel属性:

 protocol DetailViewController: class { var viewModel: ViewModel? {get set} } 

我也有几个不同的类来实现协议:

 class FormViewController: UITableViewController, DetailViewController { // ... } class MapViewController: UIViewController, DetailViewController { // ... } 

我的主视图控制器需要一个属性,可以设置任何实现DetailViewController协议的UIViewController子类。

不幸的是,我找不到任何文件如何做到这一点。 在Objective-C中,这将是微不足道的:

 @property (strong, nonatomic) UIViewController<DetailViewController>; 

看来在Swift中没有可用的语法来执行此操作。 我最近来的是在我的类定义中声明一个generics:

 class MasterViewController<T where T:UIViewController, T:DetailViewController>: UITableViewController { var detailViewController: T? // ... } 

但后来我得到一个错误,说“类'MasterViewController'没有实现其超类所需的成员”

这看起来应该像在Objective-C中一样简单,但是在任何地方我都找不到任何可以解决的问题。

从Swift 4开始,你现在可以做到这一点。

Swift 4实现了SE-0156 (Class和Subtype existentials)。

这个Objective-C语法的等价物:

 @property (strong, nonatomic) UIViewController<DetailViewController> * detailViewController; 

现在在Swift 4中看起来像这样:

 var detailViewController: UIViewController & DetailViewController 

本质上你可以定义一个variables符合的类,以及它实现的N个协议。 有关更多详细信息,请参阅链接的文档。

我想你可以通过给UIViewController添加一个(空的)扩展名,然后使用空的扩展名和你的DetailViewController的组合协议来指定你的detailViewController属性。 喜欢这个:

 protocol UIViewControllerInject {} extension UIViewController : UIViewControllerInject {} 

现在UIViewController所有子类都满足协议UIViewControllerInject 。 然后,简单地说:

 typealias DetailViewControllerComposed = protocol<DetailViewController, UIViewControllerInject> class MasterViewController : UITableViewController { var detailViewController : DetailViewControllerComposed? // ... } 

但是,这不是特别“自然”的。

===编辑,加法===

实际上,如果你使用我build议的UIViewControllerInject来定义你的DetailViewController ,你可以做得更好一些。 像这样:

 protocol UIViewControllerInject {} extension UIViewController : UIViewControllerInject {} protocol DetailViewController : UIViewControllerInject { /* ... */ } 

现在你不需要明确地编写一些东西(我的DetailViewControllerComposed ),并可以使用DetailViewController? 作为detailViewController的types。

另一种方法是为实现协议的相应UIKit视图控制器引入中间基类:

 class MyUIViewControler : UIViewController, DetailViewController ... class MyUITableViewController : UITableViewController, DetailViewController ... 

然后你inheritance你的视图控制器从这些视图控制器,而不是UIKit的。

这也不是自然的,但它并不强迫所有的UIViewControllers满足UZiewControllerInject协议GoZonerbuild议。