我如何声明一个具有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议。