Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Class conforming to protocol as function parameter in Swift

Tags:

swift

In Objective-C, it's possible to specify a class conforming to a protocol as a method parameter. For example, I could have a method that only allows a UIViewController that conforms to UITableViewDataSource:

- (void)foo:(UIViewController<UITableViewDataSource> *)vc; 

I can't find a way to do this in Swift (perhaps it's not possible yet). You can specify multiple protocols using func foo(obj: protocol<P1, P2>), but how do you require that the object is of a particular class as well?

like image 310
Martin Gordon Avatar asked Jun 05 '14 03:06

Martin Gordon


People also ask

Can a protocol inherit from a class Swift?

In Swift, protocols can inherit from one or more additional protocols. Let's see how and why to use it. Here we have a User protocol, this protocol will be getting bigger each time we add a new User requirement into it.

What is class protocol in Swift?

A protocol defines a blueprint of methods, properties, and other requirements that suit a particular task or piece of functionality. The protocol can then be adopted by a class, structure, or enumeration to provide an actual implementation of those requirements.

Can Objective C class conform to Swift protocol?

Mitrenegades solution is to use an objective-c protocol, is one way, but if you want a swift protocol, then the other would be to refactor the code so as to not use the objective-c class directly, but instead use the protocol (e.g. some protocol based factory pattern). Either way may be appropriate for your purposes.


2 Answers

You can define foo as a generic function and use type constraints to require both a class and a protocol.

Swift 4

func foo<T: UIViewController & UITableViewDataSource>(vc: T) {     ..... } 

Swift 3 (works for Swift 4 also)

func foo<T: UIViewController>(vc:T) where T:UITableViewDataSource {      .... } 

Swift 2

func foo<T: UIViewController where T: UITableViewDataSource>(vc: T) {     // access UIViewController property     let view = vc.view     // call UITableViewDataSource method     let sections = vc.numberOfSectionsInTableView?(tableView) } 
like image 160
Nate Cook Avatar answered Sep 25 '22 08:09

Nate Cook


In Swift 4 you can achieve this with the new & sign:

let vc: UIViewController & UITableViewDataSource 
like image 23
Jeroen Bakker Avatar answered Sep 21 '22 08:09

Jeroen Bakker