我的应用程序有详细视图控制器的协议,声明它们必须具有viewModel
属性:
protocol DetailViewController: class {
var viewModel: ViewModel? {get set}
}
我还有一些实现协议的不同类:
class FormViewController: UITableViewController, DetailViewController {
// ...
}
class MapViewController: UIViewController, DetailViewController {
// ...
}
我的主视图控制器需要一个可以设置为实现UIViewController
协议的任何DetailViewController
子类的属性。
很遗憾,我无法找到有关如何执行此操作的任何文档。在Objective-C中,这将是微不足道的:
@property (strong, nonatomic) UIViewController<DetailViewController>;
似乎Swift中没有任何可用的语法来执行此操作。我最接近的是在我的类定义中声明一个泛型:
class MasterViewController<T where T:UIViewController, T:DetailViewController>: UITableViewController {
var detailViewController: T?
// ...
}
但后来我得到一个错误,说&#34; Class&#39; MasterViewController&#39;没有实现其超类的必要成员&#34;
这似乎在Swift中应该像在Objective-C中一样容易,但我无法在任何地方找到任何可以表明我如何去做的事情。
答案 0 :(得分:13)
我认为您可以通过向UIViewController
添加(空)扩展程序,然后使用空扩展程序和detailViewController
的组合协议指定DetailViewController
属性来实现目标。像这样:
protocol UIViewControllerInject {}
extension UIViewController : UIViewControllerInject {}
现在UIViewController
的所有子类都满足协议UIViewControllerInject
。然后,只需:
typealias DetailViewControllerComposed = protocol<DetailViewController, UIViewControllerInject>
class MasterViewController : UITableViewController {
var detailViewController : DetailViewControllerComposed?
// ...
}
但是,这并不是特别自然的&#39;。
===编辑,添加===
实际上,如果您使用我建议的DetailViewController
定义UIViewControllerInject
,您可以做得更好一些。像这样:
protocol UIViewControllerInject {}
extension UIViewController : UIViewControllerInject {}
protocol DetailViewController : UIViewControllerInject { /* ... */ }
现在您不需要明确撰写某些内容(我的DetailViewControllerComposed
),并且可以使用DetailViewController?
作为detailViewController
的类型。
答案 1 :(得分:10)
从Swift 4开始,您现在可以执行此操作。
Swift 4实现了SE-0156(Class和Subtype存在)。
等效于Objective-C语法:
Application
现在在Swift 4中看起来像这样:
AsyncTask
基本上,您可以定义变量符合的一个类,以及它实现的N个协议。有关详细信息,请参阅链接文档。
答案 2 :(得分:2)
另一种方法是为实现协议的相应UIKit视图控制器引入中间基类:
class MyUIViewControler : UIViewController, DetailViewController ...
class MyUITableViewController : UITableViewController, DetailViewController ...
然后从这些视图控制器继承视图控制器,而不是UIKit视图控制器。
这也不自然,但它并没有像GoZoner建议的那样强迫所有UIViewControllers
满足UIViewControllerInject
协议。