My app has a protocol for detail view controllers, stating they must have a viewModel
property:
protocol DetailViewController: class {
var v
As of Swift 4, you can now do this.
Swift 4 implemented SE-0156 (Class and Subtype existentials).
The equivalent of this Objective-C syntax:
@property (strong, nonatomic) UIViewController<DetailViewController> * detailViewController;
Now looks like this in Swift 4:
var detailViewController: UIViewController & DetailViewController
Essentially you get to define one class that the variable conforms to, and N number of protocols it implements. See the linked document for more detailed information.
Another way would be to introduce intermediate base classes for the appropriate UIKit view controllers that implement the protocol:
class MyUIViewControler : UIViewController, DetailViewController ...
class MyUITableViewController : UITableViewController, DetailViewController ...
Then you inherit your view controllers from these view controllers, not the UIKit ones.
This is not natural either, but it doesn't force all your UIViewControllers
to satisfy the UIViewControllerInject
protocol as GoZoner suggested.
I think you can get there by adding an (empty) extension to UIViewController
and then specifying your detailViewController
attribute using a composed protocol of the empty extension and your DetailViewController
. Like this:
protocol UIViewControllerInject {}
extension UIViewController : UIViewControllerInject {}
Now all subclasses of UIViewController
satisfy protocol UIViewControllerInject
. Then with that, simply:
typealias DetailViewControllerComposed = protocol<DetailViewController, UIViewControllerInject>
class MasterViewController : UITableViewController {
var detailViewController : DetailViewControllerComposed?
// ...
}
But, this is not particularly 'natural'.
=== Edit, Addition ===
Actually, you could make it a bit better if you define your DetailViewController
using my suggested UIViewControllerInject
. Like such:
protocol UIViewControllerInject {}
extension UIViewController : UIViewControllerInject {}
protocol DetailViewController : UIViewControllerInject { /* ... */ }
and now you don't need to explicitly compose something (my DetailViewControllerComposed
) and can use DetailViewController?
as the type for detailViewController
.