Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I declare a variable that has a type and implements a protocol?

My app has a protocol for detail view controllers, stating they must have a viewModel property:

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

I also have a few different classes that implement the protocol:

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

My master view controller needs a property that can be set to any UIViewController subclass that implements the DetailViewController protocol.

Unfortunately I can't find any documentation on how to do this. In Objective-C it would be trivial:

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

It appears that there isn't any syntax available in Swift to do this. The closest I've come is to declare a generic in my class definition:

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

But then I get an error saying that "Class 'MasterViewController' does not implement its superclass's required members"

This seems like it should be as easy to do in Swift as it is in Objective-C, but I can't find anything anywhere that suggests how I might go about it.

like image 401
Frank Schmitt Avatar asked Aug 09 '14 01:08

Frank Schmitt


People also ask

Can we declare variables in protocol?

The protocol doesn't specify whether the property should be a stored property or a computed property—it only specifies the required property name and type. Property requirements are always declared as variable properties, prefixed with the var keyword.

How do you implement a protocol?

Protocols are basically set of rules. The way to implement them is to first of all make a state machine diagram as it completely tells that what is going to be the current state and how the state is going to change on the basis of input and what output actions are going to be performed.

What is protocol in Swift with example?

In Swift, a protocol defines a blueprint of methods or properties that can then be adopted by classes (or any other types). Here, Greet - name of the protocol. name - a gettable property.

What's the difference between a protocol and a class in Swift?

You can create objects from classes, whereas protocols are just type definitions. Try to think of protocols as being abstract definitions, whereas classes and structs are real things you can create.


2 Answers

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.

like image 150
GoZoner Avatar answered Oct 19 '22 05:10

GoZoner


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.

like image 38
Senseful Avatar answered Oct 19 '22 04:10

Senseful